Hi, Recently I wanted to take and print the address of a label. When compiling with -O2, I noticed that the address equals the function body start address if the label is not used as a goto target.
Here is an example: #include <stdio.h> int main(void) { printf("main: %p\n", main); printf("label1: %p\n", &&label1); label1: puts("---"); return 0; } compile with: $ gcc -O2 -o example1 example1.c or more specifically: $ gcc -O1 -fschedule-insns2 -o example1 example1.c Output: main: 0x562ed396216e label1: 0x562ed396216e --- (or compile with -S to see that the label is moved to the start of the function) That is not completely surprising because labels as values are not really valid outside of the originating function [1]. However when I assign the two addresses to automatic variables (which should be okay) and compare them, they are different (despite having the same value; the substraction result is 0). Passing them to an external function yields equality again (if the function is not inlined). #include <stdio.h> void compare(size_t x, size_t y) { printf("x == y : %d\n", x == y); } int main(void) { size_t m = (size_t)main; size_t l = (size_t)&&label1; printf("m: %p\n", m); printf("l: %p\n", l); printf("m == l : %d\n", m == l); printf("m - l :% d\n", m - l); compare(m, l); label1: puts("---"); return 0; } Output: m: 0x559a775cd16e l: 0x559a775cd16e m - l : 0 m == l : 0 x == y : 1 --- The reasons for this behavior probably lies in constant folding/propagation. I'm not sure whether this is technically a bug (Labels as Values / Computed Gotos are not Standard C anyway). But this is at least confusing. Maybe the label should not be moved in the first place? Regards, Flo [1] https://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html
// Compile with: // $ gcc -O2 -o example2 example2.c // or // $ gcc -O1 -fschedule-insns2 -o example2 example2.c #include <stdio.h> void compare(size_t x, size_t y) { printf("x == y : %d\n", x == y); } int main(void) { size_t m = (size_t)main; size_t l = (size_t)&&label1; printf("m: %p\n", m); printf("l: %p\n", l); printf("m == l : %d\n", m == l); printf("m - l :% d\n", m - l); compare(m, l); label1: puts("---"); return 0; }
// Compile with: // $ gcc -O2 -o example1 example1.c // or // $ gcc -O1 -fschedule-insns2 -o example1 example1.c #include <stdio.h> int main(void) { printf("main: %p\n", main); printf("label1: %p\n", &&label1); label1: puts("---"); return 0; }