我有以下C代码:

#include <stdint.h>
#include <stdio.h>

int i;
uint64_t a[] = { (uint64_t)&i, (uint64_t)&i + 0x8000000000000000 };

int main() {
    printf("%p %llx %llx\n", &i, a[0], a[1]);
}

如果我使用Microsoft Visual Studio Community 2015编译(作为C或C++),然后运行它,则输出类似于以下内容:
013E9154 13e9154 13e9154

看来我希望将+ 0x8000000000000000的高位设置为高的代码a[1]已被默默地忽略了。

但是,如果我将a的初始化移到main内,则输出将是我期望的:
00179154 179154 8000000000179154

使用a global时,为什么默默地忽略添加项?尝试加法实际上应该设置a[1]的高位还是应该导致编译器错误?

有趣的是,如果将以上代码中的+ 0x8000000000000000替换为| 0x8000000000000000,则会收到“错误C2099:初始化程序不是常量”。

编辑:即使没有强制转换,也会发生类似的问题。以下代码针对x64进行了编译,打印了3次相同的值(例如000000013FB8D180):
#include <stdio.h>

int i;
int * a[] = { &i, &i + 0x100000000 };

int main() {
    printf("%p %p %p\n", &i, a[0], a[1]);
}

最佳答案

初始化器

(uint64_t)&i + 0x8000000000000000

在C中不是有效的constant expression。它也不是仅允许将整数常量,浮点常量,枚举常量,字符常量和sizeof表达式用作操作数的算术常量表达式;也不允许不允许转换为整数类型的地址常量。

就是说,我希望Visual Studio像| 0x8000000000000000一样生成“错误C2099:初始化程序不是常量”。

不过,我不确定C++。

10-07 15:35