数据类型中signed、unsigned他们在不同数据类型中存储的不同体现:
如:char a = -1;
在将-10放进内存中时,首先你需要知道内存中存的都是补码所以应该将-10换成补码即为:0x FF FF FF FF :11111111111111111111111111111111此时若要放进char中就要发生截断成8bit 即为 0x FF :11111111
unsigned char b = -1;
同理:最终放进内存中的值为:11111111
但是你需要知道此时的11111111中的第一位将不再看作符号位
signed char c = -1;
同理:11111111
第一位将看作符号位,当然光的char和此处也是一样的
因为unsigned存在时其符号位将不存在所以此时的unsigned char a = -1;存在内存中的数值已将变成一个正数也就是11111111(255) 所以unsigned char a = -1其实存的是char类型中最大的值(11111111),他不会再通过补变回原码
所以当我们在打印时会有:
int main() { char a = -1; unsigned char b = -1; signed char c = -1; printf("%d %d %d", a, b, c);//-1 255 -1 return 0; }
那具体是如何实现打印的呢?
由前面我们可以知道,所有的数值都是以补码的形式存进内存中的。并且char 与 signed char 是相同的。所以,其实a、b、c存在内存中是一样的都是11111111,但是当我们在printf中进行使用时就会有不同(a、c一起看)
并且因为打印的是%d是有符号的整数所以在要打印的数据也应该为一个整形,所以如short、char这种小于int类型的就要进行整形提升(并且注意只要小于int类型的当遇到操作符时就会进行整形提升)
a:的补码11111111,
首先,需要进行整形提升(隐式提升,若忘了可以看->操作符的目录进行查看)补符号位:11111111111111111111111 111111111
其次,再转化成原码(因为是负数):10000000 00000000 00000000 00000001
最终:再进行打印(原码转化成10进制的值): -1
b的补码11111111
首先,需要进行整形提升补符号位,因为此处的b是一个无符号的字符类型所以其为一个正数,补符号位0:000000000000000000000000 111111111
其次再转化成原码,但此时符号位为0即为正的所以原反补相同就不需要再进行改变;
最终:再进行打印: 255
所以在通过上面的代码我们还可以发现一个知识点就是:
printf中的 %d 与 数值的类型 在整形提升前相互不会影响,即 b处他的类型是无符号的字符类型,而%d为有符号的整形,b在整形提升时仍然时一个无符号的字符类型。
而在整形提升后就会有一定的影响,即他认为内存中存的是一个有符号/无符号的整形(%d/%u)当需要打印的是有符号的整形此时就需要变成原码进行打印,而若为无符号的整形就不再需要转变成。
再如:
char a = 128
printf("%u", a )
此时先将128的补码存进char中也就是
10000000 然后整形提升后:11111111111111111111111110000000
再打印就将会打印 11111111111111111111111110000000 二进制对应的十进制:4,294,967,168
附:通过上面的习题,我觉得有必要在补充一定关于 char类型在内存中的取值范围 (另一篇blog)的知识
练习:
一、
int main() { int a = -20; unsignde int = 10; printf("%d",a + b); return 0; }
该题分析:
a、b两个变量中都要存数据进到内存,并且都是以补码的形式存进内存中
即a中存的是:-20 的补码
而b中存的是:10 的补码
在printf中%d和a+b无直接联系:所以直接相加即可:那就得到了-10的补码(虽然a+b因为算术转换变成了一个无符号的整形但是这和%d无关,当用%d打印时其仍然将你看成一个有符号的整形来进行打印)
最后通过,%d打印即可得到-10(原码)
二、
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> int main() { char arr[1000] = { 0 }; int i = 0; for (i = 0; i < 1000; i++) { arr[i] = - 1 - i; } printf("%d", strlen(arr)); return 0; }
分析:
因为char类型的范围是从-128~127
所以arr的取值就也可以是从:-128~127
第一次:arr[0] = -1 第二次:... = -2 arr[127] =-128 ... arr[254] = 1
后arr[255] = 0(此时因为strlen是遇到'\0'就会停止)
所以最终strlen最终有 0 ~ 254 (-1 到 -128 再从127 到 1 : 128 + 127)个元素 共并打印255个