Why does array overflow initialization give a warning, but no assignment overflow?

Why int a[5] = {1,2,3,4,5,6} gives a warning, and int a[5] = {1,2,3,4,5}; a[5] = 6; int a[5] = {1,2,3,4,5}; a[5] = 6; - no?

Is it good to do this when I initially declared the size of the array to be 5?

What if i don't know the size of my array? Can I declare it like this: int a[] ?

+4
source share
4 answers

Why int a [5] = {1,2,3,4,5,6} gives a warning, while int a [5] = {1,2,3,4,5}; a [5] = 6; not?

The assignment gives you a warning because you know the size of the variable in the initialization statement and clearly violate the size of your declaration. You do not have the size of the array from a in line a[6] = 6 , so for the compiler this looks fine. Of course, the level of warnings varies from compiler to compiler, and for some compilers you can specify additional warnings.

For example, using gcc, you can use the -Wextra and -Wall flags to get a lot of warnings. Getting warnings is good, because the compiler helps you find possible caveats without requiring debugging your code. Of course, they are only good if you fix them :-)

Is this good practice when I initially declared an array of size 5?

It is never recommended to assign an integer to a place that you did not declare - you cannot be sure where this value is written, and it can rewrite another variable or, even worse, partially rewrite another variable or stack. Since this type of material differs from the compiler by the compiler, as @PascalCuoq pointed out, it is called undefined behavior , and this is what you want to avoid at all costs. Of course, since it is undefined, it may happen that your program will be executed only after this announcement, but this is a very bad practice.

However, there is nothing wrong with initializing a fixed-size array if it does not change. You should avoid magic numbers and use constants instead, such as MAX_NUMBER_OF_PERMUTATIONS or CURRENCIES_SIZE .

Can I declare it like this: int a []?

Declaring it as int a[] is shorthand when you initialize a fixed array, and the compiler can specify the number of elements. For instance:

 int a[] = {1,2,3}; //this is good int b[3] = {1,2,3}; //same from above 

In the past, int a[]; was usually declared int a[]; However, it does not work in every compiler, so it should be avoided. (Thanks @PascalCuoq for pointing this out)

What if i don't know the size of my array?

If you do not know the size of your array, you must declare it as a pointer, for example int * a , and independently manage the memory using malloc , realloc , calloc and similar system calls. Please do a good job and learn about free too, the world will thank you later. You should read pointers instead of arrays if you are looking for dynamic memory allocation.

+8
source

Why int a [5] = {1,2,3,4,5,6} gives a warning, while int a [5] = {1,2,3,4,5}; a [6] = 6; not?

Warnings are just a compiler that tries to help you. The compiler should not warn every time you do something wrong. There are too many ways to write incorrect programs, and compilers cannot warn about all of them.

Is it good to do this when I initially declared the size of the array to be 5?

No. When a is an array of size 5, access to a[6] or a[5] causes undefined behavior (translation: this is very bad). The traditional saying about undefined behavior is that it allows the compiler to release daemons from the nose :

During the discussion of this group in early 1992, it was regularly noted, β€œWhen the compiler encounters [a given undefined construct], it is legal for it to make demons fly out of your nose” (meaning that the compiler can choose any arbitrary bizarre way of interpreting code without violating the ANSI standard C)

So, in short, always avoid undefined behavior in your C programs.

What if i don't know the size of my array? Can I declare this as int []?

No, you can’t. You need to know the size of your array when you declare it. int a[]; will declare an incomplete array that is not what you want ( here is a link about incomplete types, but if you ask for access the sixth element of an array with five elements, you just don't want to hear about incomplete types). If you do not know the size that you will ultimately need, find out about malloc() and realloc() .

+6
source

In your second example, the compiler does the math of the pointer to determine where to put the integer. In older C implementations, an array is not a first-class type, so there is no way to check the range. Some newer ones may detect errors outside the bounds.

If you need to dynamically allocate arrays, this is the correct template:

 int *a; // calloc( elements, size) // create an array of 6 elements, 0..5 a = calloc(6, sizeof(int)); // use like a[5]=6, be sure to free(a) later. 

Check out the calloc and free links.

+2
source

Question: Why

 int a[5] = {1,2,3,4,5,6}; 

gives a warning, and

  int a[5] = {1,2,3,4,5}; a[5] = 6; 

not?

This is actually a very good question, and I do not have a good answer to it.

As for the C language standard, initialization is a violation of the restriction, which means that the corresponding compiler must issue diagnostics and may reject the program. (gcc does this with the -pedantic-errors option, which I recommend using).

In the second case, a[5] = 6; has undefined behavior. The language does not require diagnostics, but it certainly allows one, and a smart enough compiler can warn about this. When the compiler sees the purpose of a[5] , it knows (or may know) that a has only 5 elements, and you are trying to access the 6th element. gcc at least doesn't do this, at least not with the options I tried.

Why does the standard require diagnostics for the first case, but not for the second? Since the first error can always be detected at compile time. The compiler must know how large a is because the declaration creates it; he must allocate a memory for him. In such a declaration, size is always known at compile time. (There are arrays of variable length, but you cannot use such an initializer for them.)

In a[5] = 6; the compiler will have to do more analysis to find an error that is not always possible to analyze. You could easily write:

 a[n] = 6; 

which would be just as bad if n turns out to be 5 - but the compiler will have to determine at compile time the value that n will have at run time in order to diagnose it. Compilers can sometimes perform such an analysis, but there are times when this is theoretically impossible.

So why does gcc not diagnose a particular case a[5] = 6; ? This is probably just a matter of where the gcc developers decided to devote their time and other resources.

+2
source

All Articles