int a = 0; for (int i = 1; i <= 32; i++) {
a=(a<<1)|1;
printf("\n\n----第%d次----\n有符号的32位d=%d\n \n字节sizeof=(%d)\n", i, a , sizeof(a));
if (i ==(sizeof(a))*8)
break; }
以上这段,用%d输出的值只能取有符号的32位的值,因为Int类型在内存开辟的是1个符号和31个位。如果用%hd只能取有符号的16个位。反过来,定义了一个char a=0,用%d取呢?%d会根据定义的内存大小来取,也就只取char定义的有符号的8个位。
所以,定义数据类型只是开辟了内存大小,但输入和输出的大小值,取决于格式控制符
——————
%u,是取32位无符号值,对应的是unsignd类型数据,和%d不同的是,%d会把第1位的符号也输出来,所以只能取31位值,但%u要是用在低于32位数据类型的内存值输出,就不一样了,下面会说。
%lld 取有符号位64个位数值,那如何取64位无符号的值?那就要有头文件和%“ PRIu32 ” 就可以取出64无符号全部值。但如果你用lld取的是int 定义的内存,也可以将int32位值全部取出。因为lld扩大了取出范围,从int32变为64,所以符号位被移到了第33个位,而你定义的是int,所以lld读能读取32个位全部值。
%u 不管任何情况下,都可以取32位的值,但如果低于32位的内存类型(比如short和char)。正常取没事,超过了,且数据类型没有定义unsigned,就会按自己的格式32位来取,比如:你定义了个short内存,有符号的16位,用a=(a<<1)|1;去取出32位时,%u它取出的是32位全值。而数据类型是char时, 你觉得第 7 次时%u就把 32 位全取出来了,核心原因超简单:%u从始至终都是一次性解析完整的 32 位 int 值。如果你在内存定义了个unsigned 内存为,那%u就会看懂了,哪怕你想遍历32次,它也只根据你定义的数据类型unsigned走。不会像前面那些。一下子全取出来,类型是几个位,就根据类型的几个位取。也就是说,没有unsigned的定义,%u就像个没人管控的小孩。
signed 和 unsigned 的区别是:signet int 和int 其实是一个意思,而unsignet int 是开辟了一个无符号的32内存位。%d控制符取得是有符号的32位,所以你要用%u来取出无符号的全部位值
char a=0;
scanf(“%d”,&a);
printf(“%d”,a);
上面这个例子,如果开辟的是char类型,8个位的内存,然后
用%d这个32位存入10000,
在用32位的%d取值
过程:scanf会将10000转换为二进制,然后以%d的格式符用32位的方式存内存里.
但char很牛逼,我管你几位,我定义了的内存是8位,我就取你后面8个位,因为我只看懂8个位,你后面还想用32位的%d让我输出,不好意思,我只给你我刚才存的那8位,也就是10000转成二进制是10011100010000 我只给你后面8位是0001 0000 ,这个二进制换成十进制就是16.
如果改成scanf用%c 输入10000呢?
%c的机制就是只认第一个数字(字符)1,而且会用根据ASCLL值,将第一个字符转换成二进制放进内存里,用%d取出时,换变成十进制,也就是ASCLL 1里的数值49,你看下ASCLL码值1对应的是不是49.
——————
所以你定义类型开辟了多少内存,scanf的格式控制符不管你开辟了多少,它只管用什么方式存进去,我就让你什么方式吐出来。少的可以,多的不行。就是这么牛逼严谨。