According to C99 standard 6.5.2.5 .9 the code:
int *p = (int []){2, 4};
initializes p to point to the first element of an array of two ints,
the first having the value two and the second, four. The expressions in
this compound literal are required to be constant. The unnamed object
has static storage duration.
But what happens when we do something like this:
int* arr[100];
for (int a=0; a<100; a++) {
arr[a] = (int []){2, 4};
}
is a new unnamed object
create with each iteration of the loop or is the same oject used for each iteration?
Would the result be different if we did something like this:
int* ptr = NULL;
for (int a=0; a<100; a++) {
ptr = (int []){2, 4};
}
The two possible options are: a new object is created each time the loop iterates or the same object is used for each loop iteration.
I am interested whether the behavior in this situation can somehow be deducted from what is written in the standard, or is it up to compiler to decide.
I have tested it under gcc 4.1.2 with this code:
int main(void) {
int* arr[100];
for (int a=0; a<10; a++) {
arr[a] = (int []){2, 4};
printf("%p ", arr[a]);
}
printf("\n");
}
And the result is:
0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0
0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0 0x7fff4c0010a0
0x7fff4c0010a0 0x7fff4c0010a0
I wrote some code to check caf's answer:
void fillArr(int* arr[]) {
for (int a=0; a<4; a++) {
arr[a] = (int []){a, a};
printf("%p %d | ", arr[a], arr[a][0]);
}
}
void fillArr2(int* arr[]) {
for (int a=0; a<4; a++) {
int temp[] = { a, a };
arr[a] = temp;
printf("%p %d | ", arr[a], arr[a][0]);
}
}
int main(void) {
int* arr[4];
printf("\nfillarr1 function scope\n");
fillArr(arr);
printf("\nfillArr main scope\n");
for (int a=0; a<4; a++) {
printf("%p %d | ", arr[a], arr[a][0]);
}
printf("\nfillArr2 function scope\n");
fillArr2(arr);
printf("\nfillArr2 main scope\n");
for (int a=0; a<4; a++) {
printf("%p %d | ", arr[a], arr[a][0]);
}
printf("\n");
}
And the result is (called it with valgrind to detect memory errors):
==19110== Memcheck, a memory error detector
==19110== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==19110== Using Valgrind-3.5.0 and LibVEX; rerun with -h for copyright info
==19110== Command: ./a.out
==19110==
fillarr1 function scope
0x7ff000830 0 | 0x7ff000830 1 | 0x7ff000830 2 | 0x7ff000830 3 |
fillArr main scope
==19110== Use of uninitialised value of size 8
==19110== at 0x3E33A41B1D: _itoa_word (in /lib64/libc-2.5.so)
==19110== by 0x3E33A44F44: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x400664: main (literalstest.c:26)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A41B27: _itoa_word (in /lib64/libc-2.5.so)
==19110== by 0x3E33A44F44: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x400664: main (literalstest.c:26)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A44FBE: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x400664: main (literalstest.c:26)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A4574A: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x400664: main (literalstest.c:26)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A43C49: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x400664: main (literalstest.c:26)
==19110==
0x7ff000830 864144320 | 0x7ff000830 864144320 | 0x7ff000830 864144320 | 0x7ff000830 864144320 |
fillArr2 function scope
0x7ff000830 0 | 0x7ff000830 1 | 0x7ff000830 2 | 0x7ff000830 3 |
fillArr2 main scope
==19110== Use of uninitialised value of size 8
==19110== at 0x3E33A41B1D: _itoa_word (in /lib64/libc-2.5.so)
==19110== by 0x3E33A44F44: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x4006B9: main (literalstest.c:34)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A41B27: _itoa_word (in /lib64/libc-2.5.so)
==19110== by 0x3E33A44F44: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x4006B9: main (literalstest.c:34)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A44FBE: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x4006B9: main (literalstest.c:34)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A4574A: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x4006B9: main (literalstest.c:34)
==19110==
==19110== Conditional jump or move depends on uninitialised value(s)
==19110== at 0x3E33A43C49: vfprintf (in /lib64/libc-2.5.so)
==19110== by 0x3E33A4CAF9: printf (in /lib64/libc-2.5.so)
==19110== by 0x4006B9: main (literalstest.c:34)
==19110==
0x7ff000830 864144320 | 0x7ff000830 864144320 | 0x7ff000830 864144320 | 0x7ff000830 864144320 |
==19110==
==19110== HEAP SUMMARY:
==19110== in use at exit: 0 bytes in 0 blocks
==19110== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==19110==
So the literals are available only inside the function they were declared in, go out of scope after leaving the function and after that accessing them is undefined behavior.