由于从 -128 到 -1 的字符与从 +128 到 +255 的字符相同,那么使用 unsigned char 有什么意义呢?

Since characters from -128 to -1 are same as from +128 to +255, then what is the point of using unsigned char?

#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 charsigned char呢?

因为unsigned char用于C89中的一个字节整数。

请注意 C89 中存在三种不同的 char 相关类型:charsigned charunsigned char

对于字符类型,使用char

unsigned charsigned char 用于一字节整数,如 short 用于两字节整数。您不应该真正使用 signed charunsigned char 作为字符。您也不应依赖这些值的顺序。

K & R,章节和诗歌,p. 43 和 44:

There is one subtle point about the conversion of characters to integers. The language does not specify whether variables of type char are signed or unsigned quantities. When a char is converted to an int, can it ever produce a negative integer? The answer varies from machine to machine, reflecting differences in architecture. On some machines, a char whose leftmost bit is 1 will be converted to a negative integer ("sign extension"). On others, a char is promoted to an int by adding zeros at the left end, and thus is always positive. [...] Arbitrary bit patterns stored in character variables may appear to be negative on some machines, yet positive on others. For portability, specify signed or unsigned if non-character data is to be stored in char variables.

数字的位表示是计算机存储的内容,但如果没有人(或某物)强加某种模式,它就没有任何意义。

unsigned charsigned char 模式之间的区别在于我们如何解释设置位。在一种情况下,我们决定零是最小的数字,我们可以添加位直到我们得到 0xFF 或二进制 11111111。在另一种情况下,我们决定 0x80 是最小的数字,我们可以添加位直到我们到达 0x7F

我们之所以用这种有趣的方式来表示有符号数(后一种模式)是因为它将零 0x00 大致放在序列的中间,并且因为 0xFF(这是 - 1,就在零之前)加上0x01(也就是1,就在零之后)加在一起进位,直到所有位都进位,留下0x00(-1 + 1 = 0)。同样地 -5 + 5 = 0 通过相同的机制。

为了好玩,有很多表示不同事物的位模式。例如 0x2a 可能是我们所说的 "number" 或者它可能是 * 字符。这取决于我们选择强加给位模式的上下文。

打印字符 - 没有区别:

函数 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 作为数字而不是字符,则打印差异很大。

创建不同的类型是为了告诉编译器如何"understand"一个或多个字节的位表示。例如,假设我有一个包含 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

还有,想想这个可笑的问题:

Suppose sizeof (int) == 4, since arrays of characters (unsigned char[]){UCHAR_MIN, UCHAR_MIN, UCHAR_MIN, UCHAR_MIN} to (unsigned char[]){UCHAR_MAX, UCHAR_MAX, UCHAR_MAX, UCHAR_MAX} are same as unsigned ints from UINT_MIN to UINT_MAX, then what is the point of using unsigned int?