C语言中,符号扩展非常常见,大体一般发生在 a =b, 而 a、b为不同数据类型情况下。
一、短数据类型扩展为长数据类型
1、要扩展的短数据类型为有符号数的
进行符号扩展,即短数据类型的符号位填充到长数据类型的高字节位(即比短数据类型多出的那一部分),保证扩展后的数值大小不变。
例如:
a)char x=10001001b; short y=x; 则y的值应为11111111 10001001b;
b)char x=00001001b; short y=x; 则y的值应为00000000 00001001b;
当短类型扩展为长类型时,但短类型与长类型分属有符号数与无符号数时,则先按本规则进行符号扩展,再将扩展后的数据直接赋给相应的长类型数据。
即只要短类型为有符号数,那么就扩展符号位,不论要赋值的长类型是否有符号或者无符号。
2、要扩展的短数据类型为无符号数的
进行零扩展,即用零来填充长数据类型的高字节位。
例如:
a)unsigned char x=10001001b; short y=x; 则y的值应为00000000 10001001b;
b)unsigned char x=00001001b; short y=x; 则y的值应为00000000 00001001b;
二、长数据类型缩减为短数据类型
是用直接截取的方法,即将长数据类型中与短数据类型长度相同的后几个字节直接截取赋值给短数据类型。
三、同一长度数据类型转换
直接将内存中的数据赋给要转化的类型,数值大小则会发生变化。其实只是数据bit码的解读方式发生了变化。
————————————————
上面部分的原文链接
参考链接C语言关于有符号和无符号变量相互赋值的探讨
四、在计算机中,数据都是以补码的形式存储,正数原码等于反码等于补码,负数的补码等于原码取反加1,负数的补码的补码等于减一取反,也等于取反加1。取反不包括符号位
比如初始化
signed char a = 11;
signed char b=-10;
前者内存存储着 0000 1011;后者内存存储着1111 0110;
有符号数的运算,因为是存储内部的二进制补码运算,补码存在的意义就是可以把减法变为加法,所以有符号数的运算,符号位要参与运算。
a+b就是0000 1011+1111 0110 = 0000 0001 为1
有符号数和无符号数运算:
不论那么多就是储存在里面的补码进行运算
五、int占用几个字节和编译器有关系,但是可以在代码中用sizeof来查看,sizeof()返回的是unsigned int类型。如下图
printf("sizeof(char) :%d\r\n",sizeof(char));
delay_ms(1000);
printf("size of (int):%d\r\n",sizeof(int));
delay_ms(1000);
printf("sizeof(short) :%d\r\n",sizeof(short));
delay_ms(1000);
printf("sizeof(long) :%d\r\n",sizeof(long));
delay_ms(1000);
printf("sizeof(long long ) :%d\r\n",sizeof(long long));
delay_ms(1000);
printf("sizeof(float) :%d\r\n",sizeof(float));
delay_ms(1000);
printf("sizeof(double):%d\r\n",sizeof(double));
delay_ms(1000);
结果如下
六、在上面基础上一定要看博文:%u %d及补码形式存储、运算、位宽、扩位等看下面的参考博文
C语言%u、%d打印的规则、数据在内存中的存储及大小端存储模式
%d,%u的形式打印,它们都表示有符号或无符号的32个bit位的整型
下图中if中i>=0的判断,因为无论正数负数都是二进制补码存储,那么i和0的比较就看i的数据类型然后解释为对应的数然后进行比较,下图里面不是255 应该是一个很大的数因为uint是32bit
上图的C给一个无符号变量赋值负数,只要数值是负数就在内存中以取反+1的补码存储,至于最后如何打印要看%d还是别的来进行扩位(根据原来是有符号与否进行决定)解释打印