操作可能在宏中未定义

时间:2014-03-30 15:49:02

标签: c gcc

伙计我接下来有两段代码从8位提取32位变量 1)首先是:

#include <stdio.h>
#include <string.h>

int main()
{
    unsigned char buffer[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee};
    unsigned char *buff = buffer;
    unsigned int  result;
    result = *buff++;
    result += *buff++ <<8;
    result += *buff++ << 16;
    result += *buff++ <<24;

    printf("result = 0x%x, *buffer = 0x%x.", result, *buff);

    return 0;
}

没有任何警告,但看起来有点蹩脚......

2)第二,我们有宏而不是那些丑陋的4行:

#include <stdio.h>
#include <string.h>

#define to32(buffer) ((unsigned int)*buffer++ | *buffer++ << 8 | *buffer++ << 16 | *buffer++ << 24)

int main()
{
    unsigned char buffer[] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee};
    unsigned char *buff = buffer;
    unsigned int  result = to32(buff);

    printf("result = 0x%x, *buffer = 0x%x.", result, *buff);

    return 0;
}

它留下了下一个警告:

main.cpp: In function 'int main()':

main.cpp:4:99: warning: operation on 'buff' may be undefined [-Wsequence-point]

 #define to32(buffer) ((unsigned int)*buffer++ | *buffer++ << 8 | *buffer++ << 16 | *buffer++ << 24)

我很困惑GCC发现什么是未定义的行为。 这是一行中的所有变化而我总结了吗?

2 个答案:

答案 0 :(得分:2)

修改 解决方案是:

static inline unsigned to32(const unsigned char *buffer)
{
    return buffer[0] | buffer[1] << 8 | buffer[1] << 16 | buffer[3] << 24;
}

如果你真的不喜欢功能,你可以用宏做同样的事情......

关于编译器警告你的那些sequence-points

此处未定义订单:

  to32(buffer) ((unsigned int)*buffer++ | *buffer++ << 8 | *buffer++ << 16 | *buffer++ << 24)
  // will be
     buffer = *buffer++;
     buffer |= *buffer++ << 8;
      ....

   // or
     buffer = *buffer++ << 8;
     buffer |= *buffer++;
    ...

如果||&&在运算符处有一个序列点,并且操作有一个从左到右的顺序。但不是|& 订单未定义,编译器可以按任何顺序执行。

答案 1 :(得分:0)

经过Buella Gabor和auguar的一些建议后,我发现我可以这样做。 它似乎是正确的

#define to32(buffer) ((unsigned int)*buffer | *(buffer+1) << 8 | *(buffer+2) << 16 | *(buffer+3) << 24)

虽然它并不能满足我的需求:(