问题描述
我正在尝试通过C以网络形式发送一个整数(更具体地说,uint32_t
个字节)。我相信我会根据Stack Overflow上的其他示例和答案正确发送数据;但是,在接收字节时,我在不破坏uint32_t
的情况下将它们强制转换/转换为strict aliasing rule
时遇到了麻烦。这是我最初尝试的一个示例:
发件人:
uint32_t num = htonl(100);
char* converted_num = (char*)#
send(client_sock,converted_num,sizeof(num),0);
接收器:
char buf[8192];
recv(socket,buf,8192,0);
uint32_t test = ntohl(*(uint32_t*)&buf);
printf("%d\n",(int)test);
虽然这似乎可行,但我收到了反馈,uint32_t test = ntohl(*(uint32_t*)&buf);
行违反了严格的别名规则。这是我修复严格的别名冲突的尝试:
char buf[8192];
recv(socket,0);
uint32_t test = ntohl(*(uint32_t*)memcpy(&(uint32_t){0},&buf[0],sizeof(uint32_t)));
printf("%d\n",(int)test);
这会导致程序崩溃,即我的问题是,在通过c(Windows)中的套接字传输整数时,如何最有效地避免违反严格的别名规则。
解决方法
您的原始代码在严格的别名上没有任何问题-谁给您反馈是不正确的。 确实存在的问题是对齐方式–没有保证scala> "cat /tmp/data/part-00000-cf540e79-d32e-413f-9d5d-1a08b6eb8d21-c000.txt".!
[1,"John",{"F":"John","L":"Smith"}]
[2,"Jane",{"F":"Jane","L":"Doe"}]
可以正确对齐char buff[8192];
以外的任何类型(尽管可能会)。您可以通过使用malloc分配缓冲区来避免该问题:
char
malloc将始终返回为任何类型适当分配的内存。然后输入您的代码
char *buf = malloc(8192);
是安全的,尽管您应该检查malloc是否成功。
,只需将其分成几行:
uint32_t tmp;
memcpy(&tmp,buf + whatever,sizeof tmp);
result = ntohl(tmp);
您也可以使其成为内联函数:
static inline uint32_t get_u32(char *from) {
uint32_t tmp;
memcpy(&tmp,from,sizeof tmp);
return ntohl(tmp);
}
...
uint32_t test = get_u32(buf + whatever);
,
使用char
代替uint32_t
并丢弃所有投射。使用正确的类型打印并使用recv()
返回的正确类型。
//char buf[8192];
uint32_t buf[8192/sizeof(uint32_t)];
//recv(socket,buf,8192,0);
ssize_t len = recv(socket,sizeof buf,0);
if (len != -1) {
if (len % sizeof *buf != 0) { ; } // TBD code to handle non-multiples of 32-bits
len /= sizeof *buf;
for (ssize_t i = 0; i< len; i++) {
//uint32_t test = ntohl(*(uint32_t*)&buf);
//printf("%d\n",(int)test);
printf("%" PRIu32 "\n",buf[i]);
}
}