我需要找到最符合标准的方法来获取指针的地址并单独存储其字节(例如,串行传输它们)。
我有以下两个版本,我认为第一个包含未定义的行为,第二个应该只包含根据 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 标准的一部分的引用:
Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.
这是否意味着不依赖于某些实现定义的行为就不可能读取数组 a
的地址?或者有什么办法可以规避吗?
最佳答案
对于指针,最好使用类型unsigned long
(或unsigned long long
)。除非有 uintptr_t
数据类型。
为什么 unsigned
?因为移位操作只对无符号整数通用。对于已签名的,它取决于平台。
所以如果你想传输地址(不管什么原因,因为地址通常是进程本地的),你可以像下面这样:
/**
* @param ptr Pointer to serialize
* @param buf Destination buffer
* @param be If 0 - little endian, 1 - big endian encoding
*/
void ptr2buf(const void *ptr, void *buf, int be)
{
uintptr_t u = (uintptr_t)ptr;
unsigned char *d = buf;
if (be)
{
/* big endian */
d += sizeof(t) - 1;
for (i = 0; i < sizeof(t); ++i)
{
*d-- = u & 0xFF;
u >>= 8;
}
}
else
{
/* little endian */
for (i = 0; i < sizeof(t); ++i)
{
*d++ = u & 0xFF;
u >>= 8;
}
}
}
关于c - 指针地址符合标准的转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16689271/