#include <stdio.h>
#include <conio.h>
int main()
{
char a=-128;
while(a<=-1)
{
printf("%c\n",a);
a++;
}
getch();
return 0;
}
上述代码的输出与下面代码的输出相同
#include <stdio.h>
#include <conio.h>
int main()
{
unsigned char a=+128;
while(a<=+254)
{
printf("%c\n",a);
a++;
}
getch();
return 0;
}
那么我们为什么要使用unsigned char
和signed char
?
答案 0 :(得分:3)
K&amp; R,章和节,p。 43和44:
关于字符转换有一个微妙的观点 整数。该语言未指定char类型的变量 是签名或未签名的数量。当char转换为int时, 能产生负整数吗?答案因机器而异 加工,反映建筑的差异。在某些机器上, 最左边的位为1的char将转换为负整数 (“符号扩展”)。在其他情况下,通过添加将char提升为int 在左端是零,因此总是积极的。 [...]任意 存储在字符变量中的位模式可能看起来是负面的 在一些机器上,但在其他机器上是积极的为了便于携带,请指定 如果要将非字符数据存储在char中,则为signed或unsigned 变量
答案 1 :(得分:2)
因为unsigned char
用于C89
中的一个字节整数。
请注意char
中有三种不同的C89
相关类型:char
,signed char
,unsigned char
。
对于字符类型,使用char
。
unsigned char
和signed char
用于一个字节整数,如short
用于两个字节的整数。您不应该将signed char
或unsigned char
用于字符。你也不应该依赖这些价值观的顺序。
答案 2 :(得分:2)
数字的位表示是计算机存储的内容,但如果没有某人(或其他东西)在其上施加模式,它并不意味着什么。
unsigned char
和signed char
模式之间的差异是我们如何解释设置位。在一种情况下,我们确定零是最小的数字,我们可以添加位,直到我们到达0xFF
或二进制11111111
。在另一种情况下,我们确定0x80
是最小的数字,我们可以添加位,直到我们到达0x7F
。
我们有一种有趣的方式来表示有符号数字(后一种模式)是因为它将0x00
大致放在序列的中间,因为0xFF
(即-1,在零之前)加0x01
(在零之后为1)加在一起进行,直到所有位都离开高端,留下0x00 (-1 + 1 = 0)
。同样-5 + 5 = 0
同样的机制。
为了好玩,有很多位模式意味着不同的东西。例如0x2a
可能是我们称之为“数字”的字符,也可能是*
字符。这取决于我们选择对位模式施加的上下文。
答案 3 :(得分:2)
使用打印字符 - 没有区别:
函数printf()
使用"%c"
并获取int
参数并将其转换为unsigned char
然后然后将其打印出来。
char a;
printf("%c\n",a); // a is converted to int, then passed to printf()
unsigned char ua;
printf("%c\n",ua); // ua is converted to int, then passed to printf()
使用打印值(数字) - 系统使用签名的char
时的差异:
char a = -1;
printf("%d\n",a); // --> -1
unsigned char ua = -1;
printf("%d\n",ua); // --> 255 (Assume 8-bit unsigned char)
注意:稀有机器的int
尺寸与char
相同,其他问题也适用。
因此,如果代码使用a
作为数字而不是字符,则打印差异很大。
答案 4 :(得分:0)
创建不同的类型以告诉编译器如何理解&#34;一个或多个字节的位表示。例如,假设我有一个包含0xFF
的字节。如果它被解释为signed char
,那么它是-1;如果它被解释为unsigned char
,那么它就是255。
在您的情况下,a
,无论是已签名还是未签名,都会被提升为int
,并传递给printf()
,后来会隐式将其转换为unsigned char
在将其作为角色打印之前。
但是让我们考虑另一个案例:
#include <stdio.h>
#include <string.h>
int main(void)
{
char a = -1;
unsigned char b;
memmove(&b, &a, 1);
printf("%d %u", a, b);
}
简单地写printf("%d %u", a, a);
几乎可以接受。 memmove()
仅用于避免未定义的行为。
我机器上的输出是:
-1 4294967295
另外,想想这个荒谬的问题:
假设
sizeof (int) == 4
,因为字符数组(unsigned char[]){UCHAR_MIN, UCHAR_MIN, UCHAR_MIN, UCHAR_MIN}
与(unsigned char[]){UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX}
相同 从unsigned int
到UINT_MIN
UINT_MAX
,那么重点是什么 使用unsigned int
?