有符号溢出和无符号溢出的讨论

C语言学习笔记

  之(unsigned及溢出总结篇(下)

        在学习了C语言进阶【暑期特别篇】深入剖析(un)signed及溢出(上)和 C语言进阶【暑期特别篇】深入剖析(un)signed及溢出(中)两篇文章后,大家是不是对有无符号有了一定的了解,但是依然会产生各种疑问,比如:定义的有符号类型的常量,发生溢出的时候以无符号类型输出会是怎样? 同样的,定义的是无符号类型的,但是以有符号类型输出又能输出个什么东西呢?

   如果你还是拿不准的话,看来还得跟随在下继续看这篇文章了!呵呵

在这篇文章中,首先我们会总结一下,然后具体看几个综合实例,相信大家看完之后应该对有无符号的问题再也没有疑问了。

一:总结(int类型作为总结)

 1.int类型的范围总结



十进制范围

二进制范围

32

unsigned  int

0~4294967295

0~ 1-1

     signed  int

-2147483648~2147483647

1000 0000 0000 0000 0..0~

0111 1111 1111 1111 1..1

16

short  unsigned   int

0~65535

0 ~ 1111 1111 1111 1111  

short  signed  int

-32768~32767

1..1 1000 0000 0000 ~

0..0 0111 1111 1111 1111

0-0 表示320.  1-1表示321.  0..0表示160.  1..1表示161.

 2.概念理解总结

1)指定类型,是指定了有效位数,并不是实际位数。计算机分配给我们的是32位即8个字节,我们指定变量ashort  intshort  int a。其实计算机给a分配了8个字节(32位),但是我们规定实际有效的位数只是后16位而已。这就是我们通常所说的short int 2个字节。

  232位中的非有效位全部都与有效位的最高位一致。如果有效位最高位为0,则非有效位全为0,反之则全为1,也就我们所说的负数。

  3.有无符号输出类型总结

1%d: 是输出有符号类型的。当用此符号打印时,只看有效位数,并且还要看最高位来决定正负

2%u: 是输出无符号类型的。 当用此符号打印时,不管原类型是什么,都看32位,并且全部都视为正数。

二:综合实例

1. 有符号短整型 下界溢出综合实例


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# include  <stdio.h>
main()
{
    /*
  有符号短整型:有效位数为16位 ,2个字节,范围【-32768,32767】
*/
  short  int  st1=- 32770 ,   //溢出
          st2=- 32769 ,   //溢出
          st3=- 32768 ,
          st4=- 32767 ,
          st5=- 32766 ;
    //分别以有符号整型%d和无符号整型%u输出
    printf( "st1=%d=%u\n" ,st1,st1);
    printf( "st2=%d=%u\n" ,st2,st2);
    printf( "st3=%d=%u\n" ,st3,st3);
    printf( "st4=%d=%u\n" ,st4,st4);
    printf( "st5=%d=%u\n\n" ,st5,st5);
}


解析:

 1-32770溢出了,-32770=-32768-2,也即是 1..1 1000 0000 0000 0000减去2,变成

0..0 0111 1111 1111 1110,所以是正的32766,因为32766是个正数,不论是有符号输出还是无符号输出,都是32766。 -32769也是一个道理。

2-32767没有溢出,有符号输出依然是-32767,但是无符号输出时候要求是正数输出,我们也已经说过,无符号%u输出要看32位,-327671..1 0111 1111 1111 1111,看32位的话,这个数的结果应该是:2^31+2^30+.....2^16+32767=4294934529

1.有符号短整型上界溢出  综合实例


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# include  <stdio.h>
main()
{
    /*
  有符号短整型:有效位数为16位 ,2个字节,范围【-32768,32767】
*/
    short  int  st1= 32765 ,
          st2= 32766 ,
          st3= 32767 ,
          st4= 32768 //溢出
          st5= 327698 ; //溢出
    //分别以有符号整型和无符号整型输出
    printf( "st1=%d=%u\n" ,st1,st1);
    printf( "st2=%d=%u\n" ,st2,st2);
    printf( "st3=%d=%u\n" ,st3,st3);
    printf( "st4=%d=%u\n" ,st4,st4);
    printf( "st5=%d=%u\n\n" ,st5,st5);
}


 解析:

1327653276632767都没有溢出,且都是正数,有无符号输出都是一样的。

232768发生了溢出,32768=32767+1,即 0..0 0111 1111 1111 11111,得到

1..1 1000 0000 0000 0000

     如果以%d输出,则只看后16位,前16为作为正负号的判断,即-1*2^15=-32768.

    如果以%u输出,则要看32位,不管原来的数是正数还是负数,都变为正数,即:

2^31+2^30+....2^16+32768=4294934528

3.无符号整型下界溢出 综合实例


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# include  <stdio.h>
main()
{
    /*
  无符号整型:有效位数为32位 ,4个字节,范围【0~4294967295】
*/
    unsigned  int  st1=- 2 , //溢出
             st2=- 1 , //溢出
             st3= 0 ,
             st4= 1 ,
             st5= 2 ;
    //分别以有符号整型和无符号整型输出
    printf( "st1=%d=%u\n" ,st1,st1);
    printf( "st2=%d=%u\n" ,st2,st2);
    printf( "st3=%d=%u\n" ,st3,st3);
    printf( "st4=%d=%u\n" ,st4,st4);
    printf( "st5=%d=%u\n\n" ,st5,st5);
}


解析:0-0表示320

 1-1-1发生了溢出,当以%d输出时,依然是-1,当以%u输出时,-1=0-1,即:0-01,虽然0-0不能再减1了,并且32位前面也没有位数了,但是我们依然认为可以向第倒数33位借一个1.也就是1 0-0减去1,结果就是: 1111 1111 1111 1111 1..1。此数4294967295

 2012都没有溢出,并且都是正数,所以他们原样输出。

4. 无符号整型下界溢出 综合实例


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# include  <stdio.h>
main()
{
    /*
  无符号整型:有效位数为32位 ,4个字节,范围【0~4294967295】
*/
    unsigned  int  st1= 4294967293 ,
             st2= 4294967294 ,
             st3= 4294967295 ,
             st4= 4294967296 //溢出
             st5= 4294967297 ; //溢出
    //分别以有符号整型和无符号整型输出
    printf( "st1=%d=%u\n" ,st1,st1);
    printf( "st2=%d=%u\n" ,st2,st2);
    printf( "st3=%d=%u\n" ,st3,st3);
    printf( "st4=%d=%u\n" ,st4,st4);
    printf( "st5=%d=%u\n\n" ,st5,st5);
}


这个解析就不用我说了吧 !

至此,关于(unsigned及溢出的问题就全部和大家探讨完了如果还有问题的话,欢迎留言询问。


  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 检测有符号位加法和无符号位加法溢出的方法如下: 1. 有符号位加法溢出检测: 有符号位加法溢出指的是两个有符号数相加后结果超出了有符号数的表示范围。例如,对于8位有符号数,其表示范围为-128~127,如果两个数相加后结果大于127或小于-128,则发生了溢出。 检测有符号位加法溢出的方法是通过判断进位标志位和溢出标志位来实现的。进位标志位表示最高位是否有进位,溢出标志位表示结果是否超出了有符号数的表示范围。 具体实现方法如下: ```c #include <stdio.h> #include <limits.h> int main() { signed char a = 100; signed char b = 50; signed char c = a + b; if ((a > 0 && b > 0 && c < 0) || (a < 0 && b < 0 && c > 0)) { printf("有符号位加法溢出\n"); } else { printf("无符号位加法未溢出\n"); } return 0; } ``` 2. 无符号位加法溢出检测: 无符号位加法溢出指的是两个无符号数相加后结果超出了无符号数的表示范围。例如,对于8位无符号数,其表示范围为0~255,如果两个数相加后结果大于255,则发生了溢出。 检测无符号位加法溢出的方法是通过判断进位标志位来实现的。进位标志位表示最高位是否有进位。 具体实现方法如下: ```c #include <stdio.h> #include <limits.h> int main() { unsigned char a = 200; unsigned char b = 100; unsigned char c = a + b; if (c < a || c < b) { printf("无符号位加法溢出\n"); } else { printf("无符号位加法未溢出\n"); } return 0; } ``` 以上是检测有符号位加法和无符号位加法溢出的方法。需要注意的是,在实际编程中,应该根据具体的数据类型和表示范围来进行判断,避免出现错误。 ### 回答2: C语言是一种强大的编程语言,其语法简单易懂,适用于各种编程需求。在编写程序时,需要注意程序的安全性和可靠性。其中一个重要的问题是溢出问题,特别是在有符号位和无符号位加法中。本文将介绍如何设计一个C语言程序来检测有符号位加法和无符号位加法的溢出。 在C语言中,有符号位加法和无符号位加法的原理都是很简单的,只是对于数据类型和溢出的处理稍有不同。有符号位加法需要考虑符号位的问题,而无符号位加法则不需要。因此,对于两种加法的溢出检测方法也不相同。 对于有符号位加法,我们需要注意的是符号位的变化。当两个正数相加,或者两个负数相加时,最高位的符号位将不会产生任何变化;但是当一个正数和一个负数相加时,符号位将会发生变化。因此,在对有符号位加法进行溢出检测时,我们需要比较符号位和运算后的结果是否一致。若不一致,则说明溢出了。具体的实现方法如下: int check_signed_overflow(int a, int b){ int c = a + b; if ((a > 0 && b > 0 && c < 0) || (a < 0 && b < 0 && c > 0)){ return 1; }else{ return 0; } } 这个函数接受两个有符号整数类型的参数a和b,然后计算它们的和c。如果a、b是正数,c也是正数,或者a、b是负数,c也是负数,那么说明没有溢出;否则就说明溢出了。 对于无符号位加法,我们只需要比较结果是否小于其中任意一个加数即可。由于无符号类型的最高位不会为符号位,因此只要结果比其中任意一个加数小,就可以确定溢出了。具体的实现方法如下: int check_unsigned_overflow(unsigned int a, unsigned int b){ unsigned int c = a + b; if (c < a || c < b){ return 1; }else{ return 0; } } 这个函数也是接受两个参数a和b,计算它们的和c。如果结果c小于其中任意一个加数a或b,就说明溢出了。 总之,有符号位加法和无符号位加法的溢出检测方法不同,需要分别考虑其特点来实现。在程序设计中,我们应该充分考虑变量的数据类型以及变量之间的关系,才能编写出安全、可靠的程序。 ### 回答3: C语言是一种常用的编程语言,常常用来进行低级别的编程任务。在C语言中,有符号位加法和无符号位加法是两种常见的加法方式。有符号位加法是指将两个有符号数相加的过程,而无符号位加法则是指将两个无符号数相加的过程。在这两种加法中,发生溢出是常见的情况。因此,设计程序来检测有符号位加法和无符号位加法溢出是很有必要的。 有符号位加法溢出是指在两个有符号数相加时,得到的结果超出了有限的数值范围,从而无法正确表示结果。这种情况通常发生在两个相反符号的数相加时,比如一个正数和一个负数相加。为了检测有符号位加法溢出,可以使用一个简单的算法,在相加之前和相加之后分别检查两个数的符号位是否相同。如果符号位不同,则发生了溢出无符号位加法溢出是指在两个无符号数相加时,结果超出了无符号数能够表示的最大范围。这种情况通常发生在两个相同的无符号数相加时,比如两个正数相加。为了检测无符号位加法溢出,可以使用一个简单的算法,只需要检查相加后的结果是否小于相加前的任意一个数即可。如果结果小于其中任意一个数,则发生了溢出。 在设计程序来检测有符号位加法和无符号位加法溢出时,需要注意的是,程序中必须考虑所有情况,并对不同的情况进行不同的处理。这种细节上的差别很容易被忽略,但是如果不注意这些问题,程序可能会漏掉溢出情况,从而导致计算结果不正确。因此,设计这样的程序需要有一定的技术能力和经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值