在编译/链接时将半地址写入结构

时间:2013-10-08 14:51:55

标签: c gcc 16-bit

我写了代码:

#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位地址的结构。 我希望得到结果链接或加工时间。

2 个答案:

答案 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 }; 中的初始化设备可以获得最大的可移植性。