繁体   English   中英

我可以通过网络以二进制形式发送整数而不必担心陷阱值带来的UB吗?

[英]Can I send an integer in binary form over the network without having to fear UB from trap values?

坦白说,这样的代码是否有效(除了缺少必要的错误检查之外,为简单起见,在此省略)?

通过Internet发送数据的代码:

uint16_t i = htons(500);

sendto(sockfd, &i, sizeof(uint16_t), 0, &dest_addr, sizeof(struct sockaddr_in));

接收数据的代码:

uint16_t i;
recvfrom(sockfd, &i, sizeof(uint16_t), 0, src_addr, sizeof(struct sockaddr_in));
i = ntohs(i);
if(i < 100 || i > 1000)
    fprintf(stderr, "Received invalid data over the network\n");
else
    do_something(i);

我担心的是,由于我读到C标准允许除unsigned char以外的任何类型的陷阱值,是否有可能以这种方式通过网络接收到这样的陷阱值,因此我将尽快拥有UB。我写i = ntohs(i)吗?

还是POSIX保证uint16_tuint32_t不会包含陷阱值?

还是不受任何官方标准的保证,但是绝大多数实现都没有uint16_tuint32_t陷阱值,因此按照该实际标准,我不必担心吗?

C99指定固定宽度类型必须是二进制补码,并且没有填充位。 标准中有关陷阱表示的位表示,在整数类型中,只有填充位会导致陷阱表示。 因此,我们甚至无需深入研究POSIX就可以看到您的代码很好。

POSIX还使所有整数类型都为2的补码(我现在找不到,要么说得如此明确,要么是POSIX中某些其他因素的结果,我不记得了)。

我认为答案是“是”。 你在做什么很好。

我认为您担心的一点是:

某些对象表示形式不必表示对象类型的值。 如果对象的存储值具有这种表示形式,并且由不具有字符类型的左值表达式读取,则该行为是不确定的。

对于uinxx_t,我不相信有任何陷阱值。 位值的所有组合都会产生一个有效数字(即对象表示形式)。 即,所有位组合都“表示对象类型的值”,因此您不能将uintxx_t初始化为陷阱值/表示。

然后,标准继续说,这是我以前从未读过的,所以这很有趣:

对于有符号整数类型...如果符号位为1,则应通过以下方式之一修改值:

—符号位0的对应值被取反(符号和大小);

—符号位的值为-(2N)(二进制补码);

—符号位的值是-(2N-1)(一个补码)。

其中哪一个是实现定义的,符号位为1且所有值位为零的值(对于前两个)还是符号位且所有值位为1(补码的值)是陷阱表示还是?正常值。

因此,如果您使用带符号的整数,则可能会出现问题,但它似乎不适用于符号的整数。

uint16_t在内存中不能包含陷阱值-有16个值位,没有填充位。 但是,地址从未被使用的未初始化局部变量将具有不确定的值。 由于在这里使用i的地址,因此它必须驻留在内存中,即使recvfrom失败,它也将具有有效的未指定值。

在发送和接收二进制数据时,您还需要考虑客户端和服务器的字节顺序。

如果您的客户端是小字节序并发送到大字节序服务器,则在服务器上,如果客户端已经将二进制数据转换为网络字节顺序,则无需将二进制数据转换回去

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM