Happened to see a usage like this:
uint8_t a = 0x1a;
...
foo(&(uint32_t){ a })
...
So I tried below code snippet:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[])
{
uint8_t a = 0x1a;
printf("0x%x\n", a);
printf("%p\n", &a);
printf("%p\n", &a 1);
printf("===============\n");
printf("0x%x\n", (uint32_t){a});
printf("%p\n", &(uint32_t){a});
printf("%p\n", (&(uint32_t){a} 1));
printf("===============\n");
printf("%d\n", (&(uint32_t){a} 1) == (&(uint32_t){a}));
printf("%ld\n", (&(uint32_t){a} 1) - (&(uint32_t){a}));
return 0;
}
On M1 MacBook, compiled successfully and ran:
$ gcc try.c -o try.bin
$
$ ./try.bin
0x1a
0x16bb773ef
0x16bb773f0
===============
0x1a
0x16bb773e4
0x16bb773e4
===============
0
2
I got confused with below questions based on the printing:
- Is
(uint32_t){a}
just a casting fora
(like(uint32_t)a
) in C language ?- If no, the values are the same
- If yes, the addresses are different
- Is
&(uint32_t){a}
and&(uint32_t){a} 1
same in this case ?- If no, the addresses are printed same
- If yes,
==
and-
proved they are different
CodePudding user response:
Per C 2018 6.5.2 and 6.5.2.5, source code of the form ( type-name ) { initializer-list }
is a compound literal. “It provides an unnamed object whose value is given by the initializer list… The value of the compound literal is that of an unnamed object initialized by the initializer list.”
It is an lvalue, and you can take its address and even modify it. If it appears outside of a function, it has static storage duration. Otherwise, it has automatic storage duration associated with its enclosing block.
Is (uint32_t){a} just a casting for a(like (uint32_t)a) in C language ?
No, (uint32_t) a
merely converts the value of a
to the type uint32_t
. The result is just a value that can be used in expressions. Its address cannot be taken. (uint32_t) {a}
creates a new object in memory.
Is
&(uint32_t){a}
and&(uint32_t){a} 1
same in this case ?
This code creates two objects. Since they are in the same enclosing block, they have essentially the same lifetime (technically the same ending time, when execution of the block ends, but slightly different starting times, when execution reaches each). Since they exist at the same time, they have different addresses. However, &(uint32_t){a} 1
points just beyond its &(uint32_t){a}
, and that location just beyond it could be the same address where the first &(uint32_t){a}
starts, so those two printf
statements could print the same address.
Note that, when printing addresses with %p
, you should convert the address to void *
, as in:
printf("%p\n", (void *) &(uint32_t){a});
printf("%p\n", (void *) (&(uint32_t){a} 1));