2014-10-02 56 views
1

地址与在静态初始化在C对地址表达

我有一个初始化两个全局静态变量代码示例(此问题被调查的早期question启发):一个是指向外部变量,另一

#include <stdint.h> 

#define UNCACHE_MASK 0xABCDEF12UL // Value of the mask to apply 

extern int memory_area; 

const void * virtual_address = &memory_area; 

const uintptr_t int_address = ((uintptr_t)&memory_area) | UNCACHE_MASK; 

我编译时得到如下:

$ gcc -c test.c 
test.c:6:1: error: initializer element is not computable at load time 
const uintptr_t int_address = ((uintptr_t)&memory_area) | UNCACHE_MASK; 
^ 

我没有太多的专家是一个expressioon从该指针计算在C中,但似乎如果&memory area有利于初始化virtual_address,它应该也适合于初始化int_address

我错过了什么?

(gcc版本4.8.2,Cygwin的在Win 7)

回答

3

常量表达式的C语言允许转换整数值到指针类型(以形成地址常量),但不是正式定义以其他方式(形成算术常数表达式)。它明确规定,“在算术常数表达式中转换运算符只能将算术类型转换为算术类型”。由于这个原因,(uintptr_t) &memory_area位违反了算术常数表达式的要求。该表达式在形式上不是一个常量表达式,因此不能用于具有静态存储持续时间的对象的初始化程序中。

因此,简而言之,&memory_area地址常量,但(uintptr_t) &memory_area不是算术常量表达式

但确实很奇怪GCC不允许它作为扩展。

+0

如果ASLR处于活动状态,则需要动态初始化,可能这就是原因。 – Deduplicator 2014-10-02 13:38:57

+0

@Deduplicator我能理解你吗? ASLR可以更新存储在静态存储器中的地址的确切值,但不能更新从这些值派生的常量? – Arkadiy 2014-10-02 14:19:32

+0

@Arkadiy:派生常量,当然,但是在需要全面运行时初始化之前有多复杂? – Deduplicator 2014-10-02 14:21:29