C 通过套接字发送整数,同时避免破坏严格的别名规则

C 通过套接字发送整数,同时避免破坏严格的别名规则,c,windows,sockets,integer,winsock,C,Windows,Sockets,Integer,Winsock,我试图通过网络发送一个C格式的整数(更具体地说,是uint32\tbytes)。根据堆栈溢出的其他示例和答案,我相信我发送的数据是正确的;但是,在接收字节时,我无法在不违反严格的别名规则的情况下将它们转换为uint32\t。以下是我最初尝试的一个示例: 发件人: uint32\u t num=htonl(100); 字符*转换的字符数=(字符*)# 发送(客户机\u sock,转换的\u num,sizeof(num),0); 接收人: char buf[8192]; recv(soc

我试图通过网络发送一个C格式的整数(更具体地说,是
uint32\t
bytes)。根据堆栈溢出的其他示例和答案,我相信我发送的数据是正确的;但是,在接收字节时,我无法在不违反
严格的别名规则的情况下将它们转换为
uint32\t
。以下是我最初尝试的一个示例:

发件人:

uint32\u t num=htonl(100);
字符*转换的字符数=(字符*)#
发送(客户机\u sock,转换的\u 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\u t test=ntohl(*(uint32\u t*)&buf)打破了严格的别名规则。下面是我修复严格别名冲突的尝试:

char buf[8192];
recv(socket, buf, 8192, 0);
uint32_t test = ntohl(*(uint32_t*)memcpy(&(uint32_t){0}, &buf[0], sizeof(uint32_t)));
printf("%d\n", (int)test);

这会导致程序崩溃,即我的问题是,在c(windows)中通过套接字传输整数时,如何最有效地避免违反严格的别名规则。

只需将其分成几行:

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);

把它分成几行:

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);

您的原始代码在严格别名方面没有任何问题——无论是谁给您的反馈都是不正确的。它确实存在的问题是对齐——没有保证
charbuff[8192]char
以外的任何类型,code>都将正确对齐(尽管可能会对齐)。通过使用malloc分配缓冲区,可以避免该问题:

char *buf = malloc(8192);
malloc将始终返回为任何类型适当分配的内存。然后你的代码

recv(socket, buf, 8192, 0);
uint32_t test = ntohl(*(uint32_t*)buf);
printf("%d\n", (int)test);

是安全的,不过您可能应该检查malloc是否成功。

您的原始代码在严格别名方面没有任何问题——无论是谁给您的反馈都是不正确的。它确实存在的问题是对齐——没有保证
charbuff[8192]char
以外的任何类型,code>都将正确对齐(尽管可能会对齐)。通过使用malloc分配缓冲区,可以避免该问题:

char *buf = malloc(8192);
malloc将始终返回为任何类型适当分配的内存。然后你的代码

recv(socket, buf, 8192, 0);
uint32_t test = ntohl(*(uint32_t*)buf);
printf("%d\n", (int)test);

是安全的,不过您可能应该检查malloc是否成功。

使用
uint32\u t
而不是
char
,并放弃所有铸造。使用正确的类型打印,并使用
recv()
返回的正确类型

//char buf[8192];
uint32_t buf[8192/尺寸(uint32_t)];
//recv(插座,buf,8192,0);
ssize_t len=recv(插座,buf,尺寸buf,0);
如果(len!=-1){
如果(len%sizeof*buf!=0){;}//TBD代码处理32位的非倍数
len/=sizeof*buf;
对于(ssize_t i=0;i
使用
uint32\u t
而不是
char
,并放弃所有铸造。使用正确的类型打印,并使用
recv()
返回的正确类型

//char buf[8192];
uint32_t buf[8192/尺寸(uint32_t)];
//recv(插座,buf,8192,0);
ssize_t len=recv(插座,buf,尺寸buf,0);
如果(len!=-1){
如果(len%sizeof*buf!=0){;}//TBD代码处理32位的非倍数
len/=sizeof*buf;
对于(ssize_t i=0;i
Minor-tidbit:将数组大小传递给函数时,尝试使用
sizeof
派生它,以避免两次键入相同的幻数(8192):
recv(socket,buf,sizeof buf,0)
您的反馈是错误的——因为数据是用
char
类型写入的(不是从其他类型复制的),所以它没有有效类型,所以会自动获取用于读取它的有效类型。没有严格的别名冲突。@chrisdd如果您的反馈是错误的,那么它是一个字符数组,对于这个数组,“有效类型”并不是这样工作的。此外,更完整的程序也可能具有未对齐的访问权限,而这些才是真正的沉默杀手。@AnttiHaapala:数据是由
recv
编写的,因此没有有效的类型。根据6.5,任何时候当您将数据复制为
char
s时,它都会保持相同的有效类型,不会得到有效类型的
char
。对齐可能是个问题,但与严格的别名无关。您使用的是什么协议?”client_sock'建议使用TCP,在这种情况下,您发布的代码无论如何都会被破坏。次要提示:当向函数传递数组大小时,尝试使用
sizeof
派生它,以避免两次键入相同的幻数(8192):
recv(socket,buf,sizeof buf,0)
您的反馈是错误的——因为数据是用
char
类型写入的(不是从其他类型复制的),所以它没有有效类型,所以会自动获取用于读取它的有效类型。没有严格的别名冲突。@chrisdd如果您的反馈是错误的,那么它是一个字符数组,对于这个数组,“有效类型”并不是这样工作的。此外,更完整的程序也可能具有未对齐的访问权限,而这些才是真正的沉默杀手。@AnttiHaapala:数据是由
recv
编写的,因此没有有效的类型。根据6.5,任何时候当您将数据复制为
char
s时,它都会保持相同的有效类型,不会得到有效类型的
char
。对齐可能是个问题,但与严格的别名无关。您使用的是什么协议?”client_sock'建议使用TCP,在这种情况下,您发布的代码无论如何都会被破坏。@entry934h我看不出您的代码有任何错误,除了它很混乱。。。也许你有一个复合文字的编译器错误…:D@user253751不,它们不是。@entry934h我看不出你的代码有任何错误,除了它很糟糕。。。也许你有一个复合文字的编译器错误…:D@use