当我们使用格式说明符打印数据时,我无法推断机器内部发生的事件。
我试图理解有符号和无符号整数的概念,结果发现:

unsigned int b=-12;
printf("%d\n",b);     //prints -12
printf("%u\n\n",b);   //prints 4294967284

我猜b实际上将-12的二进制版本存储为111111111111111111111101010。
所以,因为b是未签名的,所以b在技术上存储4294967284。
但格式说明符%d仍然会导致b的二进制值打印为其有符号版本i,e,-12。
然而,
printf("%f\n",2);    //prints 0.000000
printf("%f\n",100);   //prints 0.000000
printf("%d\n",3.2);    //prints 2147483639

printf("%d\n",3.1);    //prints 2147483637

我有点希望2按2.00000打印,3.2按3按类型转换规范打印。
为什么不发生这种情况?在机器层面到底发生了什么?

最佳答案

格式说明符和参数类型不匹配(例如使用浮点说明符"%f"打印int值)会导致未定义的行为。
记住2是一个整数值,vararg函数(比如printf)并不真正知道参数的类型。printf函数必须依赖于格式说明符才能假定参数属于指定类型。
为了更好地理解你是如何得到结果的,为了理解“内部事件”,我们首先必须做出两个假设:
系统对int类型使用32位
系统对double类型使用64位
现在发生了什么

printf("%f\n",2);    //prints 0.000000

printf函数看到"%f"说明符,并以64位double值获取下一个参数。由于您在参数列表中提供的int值只有32位,因此double值中的一半位将是未知的。然后,printf函数将打印(无效的)double值。如果不走运,一些未知位可能会导致该值成为陷阱值,从而导致崩溃。
同样地
printf("%d\n",3.2);    //prints 2147483639

printf函数获取下一个参数作为32位int值,丢失作为实际参数提供的64位double值中的一半位。究竟哪些32位被复制到内部int值取决于endianness。整数没有陷阱值,因此不会发生崩溃,只会打印意外值。

关于c - 使用格式说明符进行转换,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57609569/

10-12 19:17