use*_*685 73 c types type-conversion integer-promotion signedness
我试过执行以下程序:
#include <stdio.h>
int main() {
signed char a = -5;
unsigned char b = -5;
int c = -5;
unsigned int d = -5;
if (a == b)
printf("\r\n char is SAME!!!");
else
printf("\r\n char is DIFF!!!");
if (c == d)
printf("\r\n int is SAME!!!");
else
printf("\r\n int is DIFF!!!");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
对于这个程序,我得到输出:
char是DIFF !!! int是相同的!
为什么我们两者都有不同的输出?
输出应该如下?
char是相同的!int是相同的!
一个键盘连接.
Lun*_*din 81
这是因为C中的各种隐式类型转换规则.C程序员必须知道其中有两个:通常的算术转换和整数提升(后者是前者的一部分).
在char情况下,你有类型(signed char) == (unsigned char).这些都是小整数类型.其他这样的小整数类型是bool和short.该整数提升规则指出,当一个小的整数类型是操作的操作数,它的类型将得到提升到int,这是签署.无论类型是签名还是未签名,都会发生这种情况.
在这种情况下signed char,符号将被保留,并将被提升为int包含值-5 的符号.在它的情况下unsigned char,它包含一个值251(0xFB).它将被提升为int包含相同值的.你结束了
if( (int)-5 == (int)251 )
Run Code Online (Sandbox Code Playgroud)
在整数的情况下,您有类型(signed int) == (unsigned int).它们不是小整数类型,因此整数促销不适用.相反,它们通过通常的算术转换来平衡,该转换声明如果两个操作数具有相同的"等级"(大小)但是具有不同的符号,则将带符号的操作数转换为与无符号操作数相同的类型.你结束了
if( (unsigned int)-5 == (unsigned int)-5)
Run Code Online (Sandbox Code Playgroud)
zmb*_*mbq 36
好问题!
该int比较有效,因为这两个整数包含完全相同的位,所以他们基本上是相同的.但那是什么char?
啊,C 在各种场合暗中提升chars int.这是其中之一.你的代码说if(a==b),但编译器实际上转向的是:
if((int)a==(int)b)
Run Code Online (Sandbox Code Playgroud)
(int)a是-5,但是(int)b是251.这些肯定是不一样的.
编辑:正如@ Carbonic-Acid指出的那样,(int)b只有当a char为8位长时才是251 .如果int是32位长,(int)b则为-32764.
REDIT:如果一个字节长度不是8位,那么就会有很多评论讨论答案的本质.在这种情况下唯一的区别是,(int)b不是251而是一个不同的正数,而不是-5.这与仍然非常酷的问题无关.
Nob*_*lis 21
欢迎整数推广.如果我可以从网站引用:
如果int可以表示原始类型的所有值,则该值将转换为int; 否则,它将转换为unsigned int.这些被称为整数促销.整数促销不会更改所有其他类型.
当你进行这样的比较时,C可能会让人感到困惑,我最近对以下挑逗的一些非C编程朋友感到困惑:
#include <stdio.h>
#include <string.h>
int main()
{
char* string = "One looooooooooong string";
printf("%d\n", strlen(string));
if (strlen(string) < -1) printf("This cannot be happening :(");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
确实打印This cannot be happening :(并且似乎表明25小于-1!
然而,在下面发生的是-1表示为无符号整数,由于底层位表示在32位系统上等于4294967295.自然25小于4294967295.
但是,如果我们显式地将size_t返回的类型转换strlen为有符号整数:
if ((int)(strlen(string)) < -1)
Run Code Online (Sandbox Code Playgroud)
然后它会将25与-1进行比较,所有这些都将与世界相得益彰.
一个好的编译器应该警告你有关无符号整数和有符号整数之间的比较,但它仍然很容易被忽略(特别是如果你不启用警告).
这对Java程序员来说尤其令人困惑,因为所有原始类型都有签名.以下是James Gosling(Java的创建者之一)在这个问题上所说的话:
Gosling:对于我作为一名语言设计师而言,我现在并不像以前那样真实地认为,"简单"真正意义上的结果是我可以期待J. Random Developer在他的脑海中保留这个规范.这个定义说,例如,Java不是 - 实际上很多这些语言都有很多极端情况,这些都是没人真正理解的.测试任何C开发人员关于unsigned的问题,很快你就会发现几乎没有C开发人员真正理解无符号算法是什么,无符号算术是什么.这样的事情让C变得复杂.我认为Java的语言部分非常简单.你必须查找的库.
ams*_*ams 10
十六进制表示-5是:
signed char:0xfbsigned int:0xfffffffb将有符号数转换为无符号数时,反之亦然,编译器确实没有... 怎么办?数字是可转换的,或者不是,在这种情况下,未定义或实现定义的行为如下(我实际上没有检查哪个),并且最有效的实现定义的行为是什么都不做.
所以,十六进制表示(unsigned <type>)-5是:
unsigned char:0xfbunsigned int:0xfffffffb看起来熟悉?它们与签名版本的位数相同.
当你编写if (a == b),在哪里a和什么b类型时char,编译器实际需要读取的是什么if ((int)a == (int)b).(这是其他人正在抨击的"整数推广".)
所以,当我们转换会发生什么char来int?
signed char到32位signed int:0xfb- >0xfffffffb
-5上面的表示!unsigned char到32位signed int:0xfb- >0x000000fb
所以,a == b确实0xfffffffb == 0x000000fb=>不匹配!
并且,c == d确实0xfffffffb == 0xfffffffb=>匹配!
| 归档时间: |
|
| 查看次数: |
29479 次 |
| 最近记录: |