我写了代码:
#include <inttypes.h>
int vari;
#if 1
struct xx {
uint16_t p_vari;
} st ={
.p_vari=(uint16_t)(uintptr_t)&vari,
};
#else
struct xx {
void *p_vari;
} st ={
.p_vari=&vari,
};
#endif
int main(void) {
return 0;
}
如果我尝试在结构中写入第一个16位的地址, (代码的第一个变体)我得到了:
vari.c:9:3: error: initializer element is not constant
vari.c:9:3: error: (near initialization for 'st.p_vari')
如果我在void *(代码的第二个变体)上写地址,则gcc编译成功。
我如何制作第一个变种?
我需要它,因为gcc无法使用16位寻址, 但我需要生成包含16位地址的结构。 我希望得到结果链接或加工时间。
答案 0 :(得分:1)
在32位(或64位程序)中没有16位寻址。地址总是具有相同的大小,这取决于架构。
这里的问题是链接器只能进行特定的地址操作,而不能进行任意计算 当变量保存静态地址时,编译器会将其标记为静态地址。然后链接器和加载器知道根据实际地址更新它。但他们所能做的只是放在一个地址中 - 不要拿地址并操纵它(例如丢掉比特)。
答案 1 :(得分:0)
你的问题是全局变量是由编译器/链接器初始化的。
编译器理解何时必须使用仅在链接时知道的地址初始化void *
,但是当您尝试在编译时执行此操作时它不会理解它{如{ {1}}。尝试使用union:
uint16_t
但请注意,这只会在小端架构上产生正确的结果。使用union xx {
uint16_t p_vari_16;
void * p_vari_p;
} st ={
.p_vari_p=&vari
};
中的初始化设备可以获得最大的可移植性。