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