将char []转换为unsigned int会给:取消引用类型惩罚指针会破坏严格别名规则

时间:2014-08-28 10:17:13

标签: c++ gcc casting strict-aliasing

我在一些传统的源代码中有一句话:

#define MAXMSG 1024
...
char m_recvBuf[MAXMSG];
unsigned int msgLength = ntohl(*((unsigned int *)m_recvBuf));

这会产生以下警告:

x.cpp: In member function ‘bool xx::cccc(std::string&)’:
x.cpp:308: warning: dereferencing type-punned pointer will break strict-aliasing rules

我怎样摆脱这个警告?

我的编译行:

g++ -c -g -O2 -Wall -DDEBUG_ON -D_VERSION_=\"1.0.0\" `xml2-config --cflags` -I../src -I./common -I. -I../../test/ -o common/xx.o common/xx.cpp

$ g++ --version
g++ (GCC) 4.4.6 20110731 (Red Hat 4.4.6-3)

2 个答案:

答案 0 :(得分:3)

您的代码存在的问题是违反了strict aliasing rules,因此可能不安全。

您可以使用-Wno-strict-aliasing隐藏警告(这不会解决您的问题),修改数据结构或完全避免问题,方法是指定二进制副本的位置和长度,如Matt建议的那样(可能最好的选择):

unsigned int msgLength; 
memcpy(&msgLength, m_recvBuf, sizeof(msgLength)); 
msgLength = ntohl(msgLength);

注意:我在-O3中没有得到clang 3.4和gcc 4.8.2的错误,这意味着编译器可能已经优化了警告。无论如何,这并不能保证您的代码是安全的。

答案 1 :(得分:2)

正如之前的响应者所说,你可以改变编译标志,使警告消失。如果你开始进行一些轻微的重构,你可以用这样的联盟更清楚地解决这个问题:

#define MAXMSG 1024

union {
  char buf[MAXMSG];
  unsigned int length;
} recvbuf;

// [ read your message stream to recvbuf.buf ]

unsigned int msgLength = ntohl(recvbuf.length);