我正在阅读计算机系统:程序员的观点,我遇到了以下C文件:
foo.c的:
void f(void);
int x = 15213;
int y = 15212;
int main()
{
f();
printf("x = 0x%x y = 0x%x \n", x, y);
return 0;
}
Bar.c:
double x;
void f()
{
x = -0.0;
}
使用gcc -o foobar foo.c bar.c编译并提供以下输出:
x = 0x0 y = 0x80000000
哇。因此,int是4个字节,double是8个字节(无论如何在我的系统上),并且x的强符号在Foo.c中,x被赋予-0.0的十六进制表示,这反过来也会覆盖y!
所以我想了解更多相关信息。为什么标准C型保护措施不会在这里发挥作用?将0x0000000080000000盲目地写入ELF中存储的x,并且y恰好在它旁边并被覆盖?随意尽可能详细。
答案 0 :(得分:1)
您违反了" 一个定义规则"
外部定义是外部声明,也是一个 函数的定义(内联定义除外)或 宾语。如果使用外部链接声明的标识符 表达式(除了作为sizeof或_Alignof的操作数的一部分 运算符,其结果是整数常量),在整个某处 程序应该只有一个外部定义 标识符;否则,不得超过一个。
导致未定义的行为。基本上,对象x
有2个定义,声明也各不相同。标准说明
引用同一对象或函数的所有声明都应具有 兼容型;否则,行为未定义。
注意:
%x
用于以无符号十六进制格式打印出unsigned int,并尝试使用%x
打印出一个负数导致未定义的行为。
使用错误的格式说明符会导致未定义的行为。
答案 1 :(得分:1)
您是否注意到编译时会出现此警告。
/ usr / bin / ld:警告:符号`x'的对齐4 in /tmp/cciNZgVG.o在/tmp/cc8pYw6O.o中小于8
这是未定义的行为。不要忽视这些警告。它根据您指定的值产生答案。