当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?
我的问题的背景是网络编程.假设我想通过网络在两个程序之间发送消息.为简单起见,假设消息看起来像这样,字节顺序不是问题.我想找到一种正确,可移植且有效的方法来将这些消息定义为C结构.我知道有四种方法:显式铸造,通过联合铸造,复制和编组.
struct message {
uint16_t logical_id;
uint16_t command;
};
Run Code Online (Sandbox Code Playgroud)
void send_message(struct message *msg) {
uint8_t *bytes = (uint8_t *) msg;
/* call to write/send/sendto here */
}
void receive_message(uint8_t *bytes, size_t len) {
assert(len >= sizeof(struct message);
struct message *msg = (struct message*) bytes;
/* And now use the message */
if (msg->command == SELF_DESTRUCT)
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
我的理解是send_message不违反别名规则,因为byte/char指针可以为任何类型设置别名.但是,相反的情况并非如此,因此receive_message违反了别名规则,因此具有未定义的行为.
union message_u {
struct message m;
uint8_t bytes[sizeof(struct message)];
};
void receive_message_union(uint8_t *bytes, size_t …Run Code Online (Sandbox Code Playgroud) 我注意到一些非常奇怪的东西.说我已经定义了以下结构
typedef struct
{
uint32_t a;
uint16_t b;
uint32_t c;
} foo;
Run Code Online (Sandbox Code Playgroud)
这个结构包含在我从网络接收的大缓冲区中.
以下代码适用于x86,但我SIGBUS在ARM上收到.
extern void * buffer;
foo my_foo;
my_foo = (( foo * ) buffer)[0];
Run Code Online (Sandbox Code Playgroud)
用memcpy替换解除引用的指针解决了这个问题.
在ARM中搜索SIGBUS时,我发现这与内存对齐somwhow有关.
有人可以解释发生了什么吗?