【发布时间】:2013-05-17 08:34:50
【问题描述】:
我需要找到最符合标准的方法来获取指针的地址并单独存储其字节(例如,以串行方式传输它们)。
我在下面有两个版本,我相信第一个版本包含未定义的行为,第二个版本应该只包含根据 C99 定义的行为。但是我的工具告诉我,我对第二个也有未定义的行为。如果可能的话,有人可以确认一下,并指出一个既没有未定义行为也没有实现定义行为的解决方案?
编辑:我将类型从 int 更改为 unsigned long 以帮助找到不依赖于实现的解决方案。我还删除了“16 位宽指针”。
unsigned long a[2];
unsigned char b0, b1, b2, b3;
int main1() {
unsigned long l = (unsigned long) &(a[0]);
b0 = (l >> 24) & 0xFF;
b1 = (l >> 16) & 0xFF;
b2 = (l >> 8) & 0xFF;
b3 = l & 0xFF;
return 0;
}
typedef union { unsigned long* p; char c[sizeof(unsigned long *)]; } u;
int main2() {
u x;
x.p = a;
b0 = x.c[3];
b1 = x.c[2];
b2 = x.c[1];
b3 = x.c[0];
return 0;
}
编辑 2:添加了对有关这些程序的 C99 标准部分的引用:
任何指针类型都可以转换为整数类型。除先前规定外, 结果是实现定义的。如果结果不能用整数类型表示, 行为未定义。结果不必在任何整数的值范围内 输入。
这是否意味着不依赖某些实现定义的行为就无法读取数组a 的地址?或者有什么办法可以绕过?
【问题讨论】:
-
您确定要传输地址吗?无论如何,它们在其他主机或其他地址空间上都无效。
-
我不知道任何具有 16 位指针的 C 实现,但假设你是对的(一些小型嵌入式系统或其他东西?) main1() 没有任何问题。您显然在 main2() 中使用了 union 或其他东西,但您没有向我们展示该代码,因此我们无法帮助您。
-
int i = (int) &(a[0]);会出现问题,因为sizeof(int) != sizeof(void*)在某些系统上 -
正如我所说,我假设他对 16 位指针是正确的(在我所知道的任何系统上都不是这种情况)。唯一可能的“未定义行为”是丢弃除指针的低 16 位之外的所有内容。
-
@LeeDanielCrocker 摩托罗拉 6811 指针是 16 位的。此外,还有 8086 个“近”指针。
标签: c undefined-behavior standards-compliance