前几天遇到了这么个问题 ,在学习 unsigned char和char 和signed char的区别时 ,说char的类型到底是signed 还是unsigned 取决于编译器 。

当时写了一串代码 如下:

char a=-1;
    printf("%d\n",sizeof(a));
    printf("%d\n",a);
    printf("%u\n",a);

char unsigned char  %d  %u  _signed char

先说%d 是将数据以int型的 十进制 格式输出;

    %u 是将数据以unsigned int 的十进制格式输出;

那么为何会输出 4294967295呢? 再怎么理解 char 类型也只是占用了 一个字节  ,而这个结果分明是4个字节的最大整数啊!

为此当时还特意查看了 内存状况  如下:

char unsigned char  %d  %u  _unsigend char _02


char unsigned char  %d  %u  _字符扩展_03

查询了一下 cc在内存中表示的是 随机数 。

这就让我更难理解了:为何会输出一个 四个字节的最大int整数?


当时我百度的是 %d和%u的区别 ,,后来我知道 我的方向错了,,导致这个结果的原因是

printf 函数对于 unsigned 和signed char的区别。


1、printf中采用%d的格式输出  就是讲元素的内存块 以有符号的形式读出来,如char a=-1;

内存中就是 0xff ,这个数字用有符号的读出来 显示的就是 -1(原码,反码,补码的关系有讲)


而printf用%u的格式时 ,若被读的数是unsigned 类型,则不会有 “字符扩张”,若是signed 类型的(char short int long)都会有字符的扩展,而这个扩展在内存中是查看不到的,扩展成四个字节的数据, 具体如下:

    若要读的数据 小于0,在内存中 符号位是1,扩展的时候,不足32位的都要在前面扩展出来的位补1(因为最前面是1,类似于<< >>左移右移时的方法),这个扩展出来的数 再以无符号int型十进制读。例如本例的-1 ,内存中是0xff ,扩展之后的就是0xff ff ff ff  这样再读就是4294967295了。

而如果是 1的话 内存中是0x01 (最前面是0) 所以扩展出来的也是0,即0x00 00 00 01,再读出来也是1.

#include<stdio.h>
int main()
{
    
    char c1=1,c2=-1;
    printf("%d\n",c1);
    printf("%d\n",c2);
    printf("%u\n",c1);
    printf("%u\n",c2);
    printf("#####################\n");
    long l1=1,l2=-1;
    printf("%d\n",l1);
    printf("%d\n",l2);
    printf("%u\n",l1);
    printf("%u\n",l2);
    printf("#####################\n");
    unsigned char c3=1,c4=-1;
    printf("%d\n",c3);
    printf("%d\n",c4);
    printf("%u\n",c3);
    printf("%u\n",c4);
    printf("#####################\n");
    unsigned long l3=1,l4=-1;
    printf("%d\n",sizeof(l4));
    printf("%d\n",l3);
    printf("%d\n",l4);
    printf("%u\n",l3);
    printf("%u\n",l4);
    return 0;
}

运行结果:

char unsigned char  %d  %u  _signed char _04

注:最后的unsigned long l4=-1;在以%u输出的时候,结果也是4294967295,但是却并不是字符扩展的结果,因为它本来就占了4个字节,在内存中为0xFF FF FF FF,所以输出像是也进行了字符扩展一样。