I came across the following unexpected behaviour while programming and I do not understand why this occurs or what even is the difference between the following two cases.
Consider the following two code snippets
#include <stdint.h>
#include <stdio.h>
typedef uint64_t* bitset;
int main(int argc, char ** argv) {
bitset list[2];
list[0] = (uint64_t[2]) {(uint64_t) 0LL, (uint64_t) 0LL};
list[1] = (uint64_t[2]) {(uint64_t) 0LL, (uint64_t) 0LL};
printf("%p\n", &list[0][0]);
printf("%p\n", &list[1][0]);
return 0;
}
and
#include <stdint.h>
#include <stdio.h>
typedef uint64_t* bitset;
int main(int argc, char ** argv) {
bitset list[2];
for(int i = 0; i < 2 ; i++) {
list[i] = (uint64_t[2]) {(uint64_t) 0LL, (uint64_t) 0LL};
}
printf("%p\n", &list[0][0]);
printf("%p\n", &list[1][0]);
return 0;
}
In the first example both values point to a different location in memory as expected, but when initializing list[0] and list[1] through a for loop. Both list[0][0] and list[1][0] point to the same location in memory.
What is causing this, why is there a difference in execution between both methods. I am compiling on an Ubuntu machine and this occurs with gcc and clan.
>Solution :
When you write (uint64_t[2]){0, 0}, that expression is called a "compound literal" and scope of the array it creates is the block in the which you defined it, so after you leave the block, it is invalid to access it.
The first example looks fine, since you are only accessing your arrays inside the block in which they were created. Your second example is bad (causes undefined behavior) because the compound literal is created inside a loop iteration, and goes out of scope almost immediately after it is created, when the program reaches the end of your loop block.
If it helps you understand: I think compound literals are basically just local variables that don’t have names. Local variables go out of scope when their block ends.
You could allocate memory using malloc or some other method if you want it to last longer. Or instead of using pointers, just define bitset itself to be a struct holding two numbers. Then your array would directly contain the data you are trying to store, instead of just containing pointers that point to data that is stored elsewhere.