C中的类型转换和按位操作的结果取决于顺序
我试图打印最小的int,char,short,long而不使用头文件< limit.h>.所以按位操作将是一个不错的选择.但有些奇怪的事发生了
该声明 printf("The minimum of short: %dn",~(((unsigned short)~0) >> 1)); 给我 The minimum of short: -32768 但声明 printf("The minimum of short: %dn",~((~(unsigned short)0) >> 1)); 给我 The minimum of short: 0 这种现象也发生在char中.但它不会发生在long,int中.为什么会这样? 值得一提的是我使用VS Code作为我的编辑器.当我将光标移动到语句中的unsigned char时 printf("The minimum of char: %dn",(short)~((~(unsigned char)0) >> 1)); 它给了我一个提示(int)0而不是(unsigned char)0,这是我所期望的.为什么会这样? 解决方法
首先,您的代码都不是真正可靠的,也不会达到预期效果.
printf和所有其他变量参数长度函数都有一个功能失调的“功能”,称为默认参数提升.这意味着传递的参数的实际类型经过静默促销.小整数类型(例如char和short)被提升为已签名的int. (并且浮动被提升为两倍.)Tl; dr:printf是一个坚果功能. 因此你可以在所有你想要的各种小整数类型之间进行转换,到最后仍然会有一个提升到int.如果您对预期类型使用正确的格式说明符,则没有问题,但是您没有使用%d,这是针对int的. 此外,?运算符与C中的大多数运算符一样,对其操作数执行隐式整数提升.见Implicit type promotion rules. 话虽如此,这一行?((?(无符号短)0)>> 1)执行以下操作: >取字体0的类型为int并转换为unsigned short. 在逻辑移位的情况下,您可以获得0x7F … FF或在算术移位时获得0xFF … FF.在这种情况下,它似乎是后者,这意味着你在转换后仍然有十进制-1. 建议:研究隐式类型提升并避免在具有签名类型的操作数上使用按位运算符. 要简单地显示各种签名类型的最低2的补码值,您必须使用无符号类型做一些技巧,因为对其签名版本的按位运算是不可靠的.例: int shift = sizeof(short)*8 - 1; // 15 bits on sane systems short s = (short) (1u << shift); printf("%hdn",s); 这会将unsigned int 1u 15位移位,然后将其结果转换为short,以某种“实现定义的方式”,这意味着在两个补码系统上,您最终将0x8000转换为-32768. 然后给printf正确的格式说明符,你将从那里得到预期的结果. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |