2013-05-22 27 views
0

我需要找到最符合标准的方式来获取指针的地址并分别存储其字节(例如,串行传输)。指针地址符合标准的转换

我有两个版本,第一个包含,我相信,未定义的行为,第二个,它应该只包含根据C99定义的行为。但是我的工具告诉我,我还有第二个未定义的行为。是否有人可以确认它,并且指出一个解决方案,如果可能,既没有未定义的行为,也没有实现定义的行为?

编辑:我改变了类型从intunsigned 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的地址?还是有办法规避它?

+2

您确定要发送的地址?无论如何,它们在其他主机或另一个地址空间上都不会有效。 –

+1

我不知道任何具有16位指针的C的实现,但假设你是正确的(一些小的嵌入式系统或其他东西?)main1()没有错。你显然使用联合或main2()的东西,但是你没有向我们展示那些代码,所以我们不能帮你。 –

+0

'int i =(int)&(a [0]);'因为'sizeof(int)!= sizeof(void *)'在某些系统上con有问题 –

回答

2

对于指针,最好使用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; 
     } 
    } 
} 
+0

好的,如果我的工具告诉我所有三个程序(我的版本和你的)都有未定义的行为,那么我的工具只接受C的一个子集?行'* d-- = u&0xFF'是否包含未定义的行为?或者只是实现定义的行为?如果是这样,是否有办法避免它? – anol

+0

此代码适用于所有机器。不,你指出的线是100%正确和合规的。如果你有一些工具告诉你,否则它是毫无价值的。 –

+0

只是为了澄清我能从标准中得到什么:'u&0xFF'包含一个指针类型('u')和一个按位AND运算符。然后将指针类型转换为整数类型,根据C99标准中的6.3.2.3.6项“结果是实现定义的”,然后对转换结果执行按位运算。 换句话说,我相信如果不依赖至少一些实现定义的行为,这意味着您的解决方案(也可能是我的解决方案)都符合标准,所以无法执行此转换。 – anol