前言
此篇博客主要用来记录博主再整型提升是遇到的疑惑;
题目一
1.
//输出什么?
#include <stdio.h>
int main()
{
char a= -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d",a,b,c);
return 0;
}
首先我们要先直到在a、b、c中的补码
1、再放入数据时数据类型只是告诉我们该开辟多大的空间,至此与我们放入数据毫无关系,暂时把数据类型抛入脑后;我们只管专心求补码,然后按照大小端放进去就行了,千万不要管它是什么类型!!!!!
2、补码:
示范:
a是char只有一个字节的空间给我们存数据,至此这个类型我们再也不需要了!!!!
-1是个负数;
原码:11(最左边的1表示符号位,最右边的才是数值位)
反码:10
补码:11
然后一个字节的空间(不要考虑他是什么类型!!!)等我们去放,从低比特位开始放,显然放不满,怎么办?甚于位置补符号位直至补满!!!!;
如果我们求出来补码已经等于或超出了我们对应类型所开辟的空间,则直接按照对应的比特位读取进去,剩余没读进去的直接一刀砍断,不要了,专业术语叫做截断;!!!
我写过例子:
char a=300;
正是咱们的101100!!!
其它类型也是如此!!!!!!当然这是存数据的过程!!!!
因此回到该题:
a:11111111
b:11111111
c:11111111
然后我们用的%d打印的,%d是打印int的,所以肯定要发生整型升!!!!
这时候我们就特别需要注意数据的类型(也就是你定义时写的类型,不是数据本身的类型!!!!切记,不要搞错了!!!)
我们看到a是char,vs环境下,char被解释位signed char
那么对于a中的最高比特位会被解释为符号位!!!
于是整型提升就是直接补符号位(对于有符号数)
故a发生整型提升就是:
11111111111111111111111111111111
同理b
11111111111111111111111111111111
对于c是unsigned char,我们直接补0
00000000000000000000000011111111;
但是我们是用的%d打印的,%d打印有符号整型!!
那么提升过后的最高位就会被解释为符号位;
因此:
a、b被解释为负数,我们打印的是原码;
因此算一下它的原码:(补码的补码就是原码)
补码:11111111111111111111111111111111
反码:1000000000000000000000000000
补码:1000000000000000000000000001
也就是:-1!!!
因此:a、b打印出来就是:-1、-1;
再来看看c
最高位是0,c、被解释为一个正数;
补码:00000000000000000000000011111111;
反码:00000000000000000000000011111111;
补码:00000000000000000000000011111111;
也就是:255;c打印的就是255!!
综上:运行结果是-1、-1、255
我们来看看运行结果:
与我们运算结果一样,很nice!!!
题目二
2.
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0;
}
这不运用我们上面题目的经验:
-128
原码:11000 0000(最高位是符号位)
反码:10111 1111
补码:11000 0000
最终放入char中的就是
1000 0000;
我们再来看看,题目是用%u,又要发生整型提升:
数据类型为char,为有符号整数;
,发生整型提升,最高位补符号位;
11111111111111111111111110000000
然后我们按照%u打印,(%u打印无符号整型),最高位被解释为数值位,原反补相同;
这个数有点大,我们拿计算机算算;
我们看看程序运行是不是这样:
与我们分析的一模一样,nice~
题目三
3.
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0;
}
a:1000 0000
整型提升:
11111111111111111111111110000000
%u最高位被解释位数值位;
与上面一道题结果是一样的;
题目四
4.
int i= -20;
unsigned int j = 10;
printf("%d\n", i+j);
//按照补码的形式进行运算,最后格式化成为有符号整数
注意:我们表示的是补码
i:11111111111111111111111111101100
j:00000000000000000000000000001010
i+j由于i、j类型不一样,i会向j发生算术转换;i会变为unsigned int类型,只有类型相匹配才能进行运算;
故i+j
11111111111111111111111111110110
用的是%d打印,最高位被解释为符号位,妥妥的负数
补码:11111111111111111111111111110110
反码:10000000000000000000000000001001
补码:10000000000000000000000000001010
也就是-10,故最后打印的就是-10;
看看运行结果:
nice~~
题目五
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
}
return 0;
}
这道题printf没卵用,我们主要看看i就行了;
首先我们能确定9~0肯定都没问题,我们再来看看i=-1;
在内存中:
11111111111111111111111111111111;
然后i–参与运算时以unsigned int的形式参与;
最高位被解释为数值位,且i>=0也会发生算术转换,是连个无符号整型参与运算;那么i就会被以无符号的方式读出来,这样读出来就是一个很大的数;
我们可以确保肯定是个正数,既然是正数,就一定比0大;那么当i=-1时,循环不会停下来;后面的话,我们也可以确保肯定时一直比0大的,而且最后又会回到0的位置(从11111111111111111111111111111111开始依次-1)(读者可以自行验证)因此就会造成死循环!!
我们来看看你运行结果:
nice~
题目六
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0;
}
char能承载的范围是-128~127
那么i在[0,127]的范围内坑定没问题,那么问题坑定出在,i=128开始
a[128]=-129;
-129为整型
补码:11111111111111111111111101111111
放在char会发生放不下,专业术语就是发生截断:
实际char放的是
01111111,是char类型
最高位被解释位符号位,也就是正数
转为10进制就是:127
同理我们再来看看a[129]=-130
-130
11111111111111111111111101111110
放在char会发生放不下,专业术语就是发生截断:
实际char放的是
011111110
最高位被解释位符号位,也就是正数
转为10进制就是:126
注意与上头的二进制位比较
再来看看你a[130]=-131;
-131
11111111111111111111111101111101
放在char会发生放不下,专业术语就是发生截断:
实际char放的是
01111101,是char类型
最高位被解释位符号位,也就是正数
转为10进制就是:125
其实算到这里我们就可以大概猜测大接下来的结果是124、123、122……
我们观察到每次存入char中的二进制都在减1;
最后会减到0
我们strlen遇到‘\0’停下来也就是数字0,并且是不算0的;
那么通过我们值之前的运算结果是
(-1~-128)+(127 ~ 1)
中间包含了-128~127的所有数,除了0,也就是strlen总共会计算255次;
我们看看运行结果:
题目七
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}
我们知道unsigned char的范围是[0~255],那我们来看看最后一次
i=256时会发生什么;
原码:0100000000
反码:0100000000
补码:0100000000
放入unsigned char中放不下,会发生截断,实际放进去的是
00000000,按照unsigned char方式读出来就是0
i<=255参与运算是会发生算术转换也就是0<=255,也就是i中放的是0,又回到初始条件了,又重0开始了,那么不就是死循环了吗?
我们来看看运行结果:
以上是博主对于整型提升的练习;