2014-10-02 54 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