有符号变量与无符号变量的值的转换

本文详细分析了一段C语言代码,涉及无符号整型与有符号整型混合运算时的溢出和取值范围问题。通过实例解释了在运算过程中负数转换为无符号整型后的补码表示,以及如何判断运算结果。最后,讨论了不同整型数据在内存中的存储方式,包括原码和补码的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


#include <stdio.h>  
  
char getChar (int x,int y)  
{  
    char c;   
    unsigned int a = x;  
  
    (a+y > 10) ? (c = 1): (c = 2);  
  
    return c;  
}   
  
int main (void)  
{  
    char c1 = getChar(7,4);  
    char c2 = getChar(7,-7);  
    char c3 = getChar(7,-8);  
    char c4 = getChar(-6,7);  
      
    printf("c1 = %d\n",c1);  
    printf("c2 = %d\n",c2);  
    printf("c3 = %d\n",c3);  
    printf("c4 = %d\n",c4);  
      
    return 0;  
}  

程序输出结果为:

c1 = 1;

c2 = 2;

c3 = 1;

c4 = 2;

首先说明getChar()函数的作用:将参数x的值转换为无符号整形后再与y相加。其结果与101进行比较,如果大于10则函数返回1,否则返回2。

注意:当表达式中存在有符号类型和无符号类型时,所有的操作数都自动转换为无符号型。

因此y值会首先自动转换成无符号的整数,然后和a相加,最后再与10进行比较。

以下是打印的各个值的分析:

c1:传入参数分别为7和4,两个数相加后为11,大于10,c1返回1;

c2:传入参数分别为7和-7,负数在转为无符号整数数时会先求出其补码,在32位的编译器中,-7的原码为1000 0000 0000 0000 0000 0000 0000 0111,

补码为1111 1111 1111 1111 1111 1111 1111 1001,7的补码为0000 0000 0000 0000 0000 0000 0000 0111,相加再转换为十进制为4294967296,而无符号整形的范围 为

0~4294967295,显然溢出了1,其最终值为0,0小于10,所以c2 = 2;

c3:传入参数分别为7和-8,同上,a+y = 4294967295 ,刚好达到无符号整型的极限,大于10,所以c3 = 1;

c4:传入参数分别为-6和7,同上,a+y = 4294967297,溢出2,其最终值为1,小于10,所以c3 = 2;

 C语言中提供了很多整数类型(整型),主要区别在于它们取值范围的大小。int代表有符号的整数,也就是说,用int声明的变量可以是正数也可以是负数,也可以是零,但是只能是整数。
比如:int a = 3; int b = 0; int c = -5;
以上这些都是合法的。
int的取值范围因机器而异,一般而言,在较旧的PC上,int值在内存中一般是按2个字节(16位)进行存储的,在较新的PC以及工作站和大型机上,int值在内存中一般是按照4个字节(32位)进行存储的。


C语言中将基本数据类型划分为signed(有符号)和unsigned(无符号)两大类。
例如,初始化变量int a = -3;其实它等价于signed int a = -3;关键字signed在这里可以省略,因为C语言默认就是有符号类型的,如果要定义无符号类型的数(也就是0和正整数)可以这样定义,unsigned int b = 5;

为了说明清楚signed和unsigned的区别,首先需要了解数据在内存中是如何存储的,在计算机中所有的数据都是按照二进制进行存储的(以下假设在字长为2个字节的机器上来表示)。

举个例子来说,unsigned  int a = 1; 变量a在内存中就是以00000000 00000001来存储的,用图表的形式表示:

 因为这里是unsigned  int,它是无符号整型,所以的它的16位全部用来表示数据。

int b = -1;

这里情况就稍微有点复杂了,注意数字1和-1在内存中的存储是完全不一样的,请看,

在计算机中,整数是以原码的形式存储的,而负数是以补码的形式存储的,原码大家都知道也就是它对应的二进制码,那什么是补码呢,就是原码的反码加1,反码就是原码的各位取反,例如-1的补码是:

首先1的原码是                     00000000 00000001

其次取它的反码是                 11111111 11111110

最后在其反码的基础上加上1   11111111 11111111

得到-1的补码是,11111111 11111111

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值