Why in C can I initialize more values than the size of an array? - Stack Overflow

This array has a size of 1 but I can initialize it with these values, then I can even set more values a

This array has a size of 1 but I can initialize it with these values, then I can even set more values after I instantiate the array and it still works. I don't understand why.

int array[1] = {12,2,12,12,12,31};

printf("%d\n",array[1]);
printf("%d\n",array[0]);

array[1] = 1;
array[8] = 3;
printf("%d\n",array[1]);// 1 It works. Why?
printf("%d\n",array[8]);// 3 It works. Why?

This array has a size of 1 but I can initialize it with these values, then I can even set more values after I instantiate the array and it still works. I don't understand why.

int array[1] = {12,2,12,12,12,31};

printf("%d\n",array[1]);
printf("%d\n",array[0]);

array[1] = 1;
array[8] = 3;
printf("%d\n",array[1]);// 1 It works. Why?
printf("%d\n",array[8]);// 3 It works. Why?
Share Improve this question edited Mar 8 at 17:59 Daniel Walker 6,8247 gold badges24 silver badges62 bronze badges asked Mar 8 at 16:33 JeJe 1773 bronze badges 4
  • 7 I would guess that when you compiled the program, the compiler gave you warnings. When I compiled your code sample, I got two distinct warnings, "main.c|6|warning: excess elements in array initializer|" and "main.c|8|warning: array subscript 1 is above array bounds of ‘int[1]’ [-Warray-bounds]|". Compiler warnings usually are a precursor to undefined behavior, which means the program might run and produce printed detail, or may cause a segment fault. Always review and address compiler warnings. – NoDakker Commented Mar 8 at 16:41
  • Such things may 'work' for the same reason that you might use the wrong cupboard by mistake, and when you return the things are magically still there. – Weather Vane Commented Mar 8 at 16:49
  • MS Visual C won't compile that code (when properly framed) - it's an error. – Weather Vane Commented Mar 8 at 16:51
  • @WeatherVane: Some compilers may use the same logic to handle arrays with unspecified size as larger sizes, treating the empty argument as zero but then expanding the size of an array to accommodate whatever data are provided. – supercat Commented Mar 9 at 1:20
Add a comment  | 

3 Answers 3

Reset to default 3

The original code line:

int array[1] = {12,2,12,12,12,31};

In standard C (as per ISO/IEC 9899 standard), this is a constraint violation. A constraint violation means the code is simply invalid and does not conform to the standard. According to the C standard (C17, §6.7.9 Initialization):

"No initializer shall attempt to provide a value for an object not contained within the entity being initialized."

Thus, the compiler must issue a diagnostic (at least a warning, typically an error) for this code. The standard explicitly forbids providing more initializers than there are elements in the array, making this particular snippet non-standard and invalid.

The separate issue, demonstrated by:

array[1] = 1;
array[8] = 3;

In standard-compliant code (assuming the array was properly initialized), accessing or writing behind array bounds is undefined behaviour (UB). UB means the standard imposes no requirements on the program's behaviour; it could seemingly "work", crash, corrupt memory, or exhibit any other unpredictable behaviour.

The main problem here is that int array[1] = {12,2,12,12,12,31}; is not even valid C. It is a constraint violation (see ISO C23 6.7.11) "No initializer shall attempt to provide a value for an object not contained within the entity being initialized."

A conforming compiler must inform you about this. The problem is that as long as it informs you with a warning/error etc, the compiler isn't required to do anything else (What must a C compiler do when it finds an error?). It can refuse to compile the code or it could compile some sort of strange "not C" executable anyway. Now of course what a "not C but something else" executable might do is anyone's guess, since it isn't documented anywhere.

If you are unfortunate to compile with a gcc-like compiler and use the default compiler settings, there's some lax extension allowing non-standard initialization lists - which in this case apparently does not mean that the compiler will handle the array gracefully with non-standard C extensions. Instead it will cook up some sort of madness executable where it writes out of bounds on the stack. Which if you are unlucky can pass unnoticed with no optimizations on, no stack canaries in place etc.

As soon as you enable optimizations, the program immediately breaks completely. For example clang -O3 just prints gibberish for this code. Why gcc and clang thinks that generating a broken "non C" executable here is useful for any programmer, I have no idea.

The best way to avoid this is to never compile with gcc or clang using the default settings, but to enable strict conformance so that the compiler will not hide away bugs or generate executables out of invalid C. What compiler options are recommended for beginners learning C?

With strict settings enabled, for example gcc -std=c23 -pedantic-errors, you get compiler errors when you write invalid C and don't have to worry about bugs created by the compiler generating "not C" executables.

As others pointed out, your compiler probably will throw warnings.

To give you a straight answer, what is happening is that you are defining a symbol associated witht the array name "array" of one element, then the program places the initializer values starting from address &a[0] independently from the associated array size.

Which means sizeof(array) should still return the size of a single int and any operation of accessing elements of array in index greater than 0 will generate compiler warnings.

Probably, if you were to define another int variable after the array with an assigned value, the second element of the array initializer will be replaced in memory by the former.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744891404a4599436.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信