1

我写了代码:

#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 位地址的结构。我想在链接或编译时得到结果。

4

2 回答 2

1

在 32 位(或 64 位程序)中没有 16 位寻址这样的东西。地址总是具有相同的大小,这取决于架构。

这里的问题是链接器只能进行特定的地址操作,而不是任意计算。
当变量保存静态地址时,编译器将其标记为静态地址。然后链接器和加载器知道根据真实地址更新它。但他们所能做的只是放入一个地址 - 而不是获取地址并对其进行操作(例如丢弃位)。

于 2013-10-08T15:03:11.180 回答
0

您的问题是全局变量是由编译器/链接器初始化的。

编译器理解何时必须void *使用仅在链接时才知道的地址初始化 a,但是当您尝试在编译时执行它时它不理解它,就像uint16_t. 尝试使用联合:

union xx {
  uint16_t p_vari_16;
  void * p_vari_p;
} st ={
  .p_vari_p=&vari
};

但请注意,这只会导致小端架构上的正确结果。在您的中使用初始化程序main以获得最大的可移植性。

于 2013-10-08T15:01:04.900 回答