Похоже, что GCC с некоторой оптимизацией считает, что два указателя из разных единиц перевода никогда не могут быть одинаковыми, даже если они на самом деле одинаковы.
код:
main.c
#include <stdint.h>
#include <stdio.h>
int a __attribute__((section("test")));
extern int b;
void check(int cond) { puts(cond ? "TRUE" : "FALSE"); }
int main() {
int * p = &a + 1;
check(
(p == &b)
==
((uintptr_t)p == (uintptr_t)&b)
);
check(p == &b);
check((uintptr_t)p == (uintptr_t)&b);
return 0;
}
b.c
int b __attribute__((section("test")));
Если я скомпилирую его с -O0, он печатает
TRUE
TRUE
TRUE
Но с -O1
FALSE
FALSE
TRUE
Итак, p
и &b
на самом деле одно и то же значение, но компилятор оптимизировал их сравнение, полагая, что они никогда не могут быть равными.
Я не могу понять, какая оптимизация сделала это.
Это не похоже на строгий псевдоним, потому что указатели имеют один тип, а параметр -fstrict-aliasing
не делает этого.
Является ли это документированным поведением? Или это ошибка?