C语言中有符号与无符号

--事物的难度远远低于对事物的恐惧!  

    经过养成记1,已经有一个很好的开端,但革命尚未成功,坚持就是胜利!现在我们来分析下C语言中的有符号数与无符号数。我们知道,计算机只能识别二进制0和1,那么我们在程序中写的-12,计算机该怎么去识别这个"-"号?计算机怎么知道我们写的数,是正数还是负数?现在就一起来揭开这层面纱!

    其实前辈大佬们早就对此作了规定了:把数据类型的最高位作为标识数据的符号位

    -最高位为1:表明这个数是负数

    -最高位为0:表明这个数是正数

下边直接上代码,实践是检验真理的唯一标准!

int main()
{
	char c = -5;
	short s = 5;
	int i = -1;
	
	//下边三条语句,只保留变量的最高位(符号位),其余置零
	int sign_c = (c & 0x80);	//拆开就是 ( c 按位与上二进制1000 0000 )
	int sign_s = (s & 0x8000);	//同上,仅仅变量占用内存大小不同
	int sign_i = (i & 0x80000000);	//同上

	printf( "%d\n", (sign_c != 0) );
	printf( "%d\n", (sign_s != 0) );
	printf( "%d\n", (sign_i != 0) );

	return 0;
}

输出为:很明显了,变量c和变量i因为是负数,所以最高位为1,而变量s为正数,所以最高位为0。码不余欺也!

经过简单的实验,我们接着来分析,

一、有符号数在计算机中的的表示方法:在计算机内部,是用补码表示有符号数

-正数的补码是其本身

-负数的补码为负数的绝对值得各个位取反加1

举个例子:

8位整数 5的补码为:0000 0101

8位整数 -7的补码为:取绝对值|-7| = 7 --> 二进制为 0000 0111 --> 各个位取反 1111 1000 -->最后加1 -->1111 1001,所 以-7在计算机中就表示为1111 1001。

16位整数 20的补码为:0000 0000 0001 0100

16位整数 -13的补码为:1111 1111 1111 0011(可自行推导)

二、无符号数在计算机中的表示方法:计算机用原码表示无符号数

-无符号数默认为正数n

-无符号数没有符号位

无符号数最小值为0,最大值为其所占的位数全为1时的值。例如 8位无符号整数,最小值为0,最大值为二进制1111 1111,转换为十进制就是255。

对于固定长度的无符号数,

MAX_VALUE + 1 = MIN_VALUE

        MIN_VALUE - 1 = MAX_VALUE

C语言中变量默认 为有符号的类型,如要将变量声明为无符号数,则需要使用unsigned关键字(C语言中只有整数类型能够声明为unsigned无符号变量)。

#include <stdio.h>

int main()
{
	int i;		//默认i为有符号数
	signed int j;	//显示声明j为有符号数
	unsigned char min_value = 0;	//显示声明k为无符号数
	unsigned char max_value = 255;
	unsigned char sub_result = min_value - 1;	//无符号数最小值 - 1 = 最大值
	unsigned char add_result = max_value + 1;	//无符号数最大值 + 1 = 最小值

	printf( "%d\n", sub_result );	//分析输出 255
	printf( "%d\n", add_result );	//分析输出 0
	return 0;
}

输出结果如下:码不余欺也!

 

问题思考:当有符号数遇到无符号数,会碰撞出什么火花?直接看下边代码,猜测下会输出什么。。。

#include <stdio.h>

int main()
{
	unsigned char i = 5;
	char j = -10;

	if( (i + j) > 0 )    // 条件为真?还是为假?
	{
		printf("i + j > 0\n");
	}
	else
	{
		printf("i + j <= 0\n");
	}

	return 0;
}

输出如下:问题来了,我们表面看到的(5 + (-10)) > 0 居然!然而计算机是不会骗人的,且听我慢慢道来。。。。

咳咳,记住了,当有符号数与无符号数一起运算时,会将有符号数转换为无符号数!

所以上边的 无符号数5  与有符号数-10做运算时,会将-10转换成无符号数,通过前边我们描述的负数在计算机中的表示方式,可以推导出-10在计算机中的值为二进制11110110,这个被当成无符号数,这个数得多大啊,5 加上它,和肯定大于0!所以,还是码不余欺也!

再来思考个问题:下边代码会有什么输出?欢迎各位留言

#include <stdio.h>

int main()
{
    unsigned int i = 0;
    
    for(i=9; i>=0; i--)
    {
        printf("i = %u\n", i);
    }
    
    return 0;
}

总结:

1、有符号数用补码表示

    -正数的符号位为0

    -负数的符号位为1

2、无符号数用原码表示

    -无符号数没有符号位

    -无符号数只用于表示正数

3、unsigned只能用于修饰整数类型的变量

4、当有符号数与无符号数进行混合运算时,会将有符号数转换为无符号数,在做运算,运算结果为无符号数。

 

  • 21
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值