[英]why char a=-1 is different from unsigned char b=-1, in C programming
i have written a small program below. 我在下面写了一个小程序。
#include <stdio.h>
main(){
char a=-1;
unsigned char b=-1;
printf("%d %d\n",a,b);
printf("%x %x\n",a,b);
if(a==b) printf("equal\n");
else printf("not equal\n");
}
The output of the prog is : 该编的输出为:
-1 255
ffffffff ff
not equal
since char is only one byte and -1 is represented in 2's complement form, i thought that 0xff will be stored in both a & b and hence both should be equal. 由于char仅为一个字节,并且-1以2的补码形式表示,我认为0xff将同时存储在a和b中,因此两者应相等。 Can anyone let me know why they are different and why hex rep'n of a is 0xffffffff & not 0xff.
谁能告诉我为什么它们不同以及为什么a的十六进制表示是0xffffffff而不是0xff。 i got a related link http://embeddedgurus.com/stack-overflow/2009/08/a-tutorial-on-signed-and-unsigned-integers/ but i couldn't get the answer.
我有一个相关的链接http://embeddedgurus.com/stack-overflow/2009/08/a-tutorial-on-signed-and-unsigned-integers/,但我找不到答案。 any help will be greatly appreciated.
任何帮助将不胜感激。 thanks.
谢谢。
They are the same. 他们是一样的。 Or rather, their underlying representation is the same (under the assumption that your compiler use two-complement form).
或者,它们的基本表示形式是相同的(假设您的编译器使用两个补码形式)。
On the other hand, the values they represent are -1 and 255. 另一方面,它们表示的值为-1和255。
When you print them, they are extended to the data type int
. 当您打印它们时,它们将扩展为
int
数据类型。 unsigned char
is zero-extended whereas a signed char is sign extended, which accounts for the differences you see. unsigned char
是零扩展的,而signed char是符号扩展的,这说明了您看到的差异。
The same extension occurs when you compare the two values. 比较两个值时,会发生相同的扩展名。
a == b
don't compare the underlying representations, instead, it extends both values to int
so it compares 255 with -1, which isn't equal. a == b
不比较基础表示,而是将两个值都扩展为int
因此将255与-1比较,这是不相等的。
Note that a plain char
may be either signed or unsigned. 请注意,普通
char
可以是有符号的也可以是无符号的。 In your environment, it is obviously signed. 在您的环境中,显然已签名。
The char
type is something of an anomaly in that it is not the same as either signed char
or unsigned char
(unlike the other integer types - short
, int
, long
, etc - which are implicitly signed unless explicitly declared unsigned
). char
类型是一种异常,因为它与有signed char
或unsigned char
不同(不同于其他整数类型short
, int
, long
等-除非明确声明为unsigned
否则它们是隐式unsigned
)。 Whether char
is actually signed or not is implementation-dependent, and some compilers even let you specify the signedness via a command line switch. char
是否实际签名取决于实现,并且某些编译器甚至允许您通过命令行开关指定签名。
Bottom line: never assume that char
is signed or unsigned - if you actually require a signed or unsigned 8 bit quantity then use signed char
or unsigned char
explicitly, or better still, use int8_t
or uint8_t
from <stdint.h>
. 底线:永远不要假设
char
是带符号的或无符号的-如果您实际上需要带符号的或无符号的8位数字,则显式使用带signed char
或unsigned char
,或者更好的是,使用<stdint.h>
int8_t
或uint8_t
。
A signed int
is signed, an unsigned int
is unsigned. 一个
signed int
签订后,一个unsigned int
是无符号。 If you use just int
, it implies signed int
. 如果仅使用
int
,则表示signed int
。 Same is true for short
, long
or long long
. short
, long
或long long
也是如此。 Yet it isn't true for char
. 但是,对于
char
并非如此。 A signed char
is signed, an unsigned char
is unsigned, but just char
may be either signed or unsigned. 一个
signed char
是签名的,一个unsigned char
是未签名的,但是只有char
可以是签名的也可以是未签名的。 The data type char is supposed to hold a "character", hence the name, so it's not "really" an integer type to hold an integer number to be used in calculations. 数据类型char应该包含一个“字符”,也就是这个名称,因此它不是“真正”一个整数类型来保存要在计算中使用的整数。 Of course a character is in reality an integer of some kind but of which kind is implementation dependent (the C standard does not force any specific kind).
当然,字符实际上是某种整数,但是哪种类型取决于实现(C标准不强制使用任何特定的类型)。 So if you want to use the char type for integer values (also used in calculations), always use
signed char
or unsigned char
explicitly and only use just char
when you are really dealing with characters or when it makes absolutely no difference for your code if char is signed or unsigned. 因此,如果要将char类型用于整数值(也在计算中使用),请始终明确使用有
signed char
或unsigned char
并且仅在真正处理字符或对代码绝对没有区别时才使用char
字符已签名或未签名。
The comparison fails because your implementation defines char
to be in fact signed char
, so you are comparing a signed char
to an unsigned char
in your final if
statement. 因为你实现定义比较失败
char
是其实signed char
,让您比较一个signed char
到一个unsigned char
在最终if
语句。 Whenever you are comparing two integers of different type, the compiler converts both values to the same type according to the rules of the C standard before it actually performs the comparison. 每当您比较两个不同类型的整数时,编译器都会在实际执行比较之前根据C标准的规则将两个值转换为相同类型。 In your case, this means the C compiler actually does tho following:
在您的情况下,这意味着C编译器实际上会执行以下操作:
if((int)a==(int)b) printf("equal\n");
else printf("not equal\n");
}
And now it should be obvious why those two values don't match. 现在很明显,为什么这两个值不匹配。
(int)a
has a value of -1
, however (int)b
has a value of 255
, and these two values are not equal. (int)a
的值为-1
,但是(int)b
的值为255
,并且这两个值不相等。
According to the rules of type promotion , char
(in your case signed) is promoted to int
and unsigned char
is also promoted to int
. 根据类型提升的规则,
char
(在您的情况下为signed)将提升为int
而unsigned char
也将提升为int
。 The ISO C 2011 standard says: ISO C 2011标准说:
If an int can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int;
如果一个int可以表示原始类型的所有值(受位字段的宽度限制),则该值将转换为int; otherwise, it is converted to an unsigned int.
否则,它将转换为unsigned int。 These are called the integer promotions.) All other types are unchanged by the integer promotions.
这些称为整数促销。)所有其他类型均不受整数促销的影响。
The integer promotions preserve value including sign.
整数促销保留包括符号在内的价值。 As discussed earlier, whether a ''plain'' char is treated as signed is implementation-defined.
如前所述,是否将“普通”字符视为已签名是实现定义的。
While there is some ambiguity around a plain "char" (see Is char signed or unsigned by default? ) that's not the only thing that's going on here I think. 尽管在普通的“字符”周围存在一些歧义(请参见默认情况下,字符是有符号的还是无符号的? ),但我认为这并不是唯一的事情。
A literal -1 is an integer, it won't (sizeof(int)>sizeof(char), for arguments sake) "fit" into a char.The two-complement bit pattern 0xffff (32 bit int for arguments sake) is truncated and copied here. 文字-1是整数,不会(为了参数而将sizeof(int)> sizeof(char))“适合”到char中。两个补码的位模式0xffff(为参数而为32位int)为被截断并复制到此处。
When you call printf() the parameters are promoted to integer type, a signed type is "sign-extended", but the unsigned "b" is not, and zero padded. 当您调用printf()时,参数将提升为整数类型,带符号类型为“符号扩展”,但不带符号的“ b”则为零,且填充为零。 When you use "==" with two distinct types a similar (but not necessarily identical) type conversion is performed (aka the "usual arithmetic conversions").
当您将“ ==”与两个不同的类型一起使用时,将执行类似(但不一定相同)的类型转换(也称为“通常的算术转换”)。
See also Default argument promotions in C function calls and Signed and unsigned, and how bit extension works in C . 另请参见C函数调用和Signed和Unsigned中的 默认参数提升 ,以及C中的位扩展如何工作 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.