C语言不匹配的整形转换详解

本文通过分析《Cprimerplus》中不匹配的整形转换代码,探讨了不同整型之间的转换原理,涉及原码、反码、补码的概念,并从机器码层面解释了转换结果。代码示例中展示了short、int、unsigned等类型在正负数值转换时的细节,揭示了底层数据表示对转换的影响。

背景:近期翻看《C primer plus》第6版,书中在第四章有写不匹配的整形转换的代码和分析。虽然书中的分析思路可以解释的通,但是我认为还有一种更偏向底层的分析思路会更直观,所以写这篇文章记录下,如有错误敬请大家批评指正。

本文布局:第一部分是不匹配的整形转换代码(基于书中的代码的基础上做了些修改),第二部分是该代码对应的输出结果的截图,第三部分尝试从机器码这样偏底层的角度来解释这样的结果,第四部分谈下我对本文中的这种偏向底层的分析思路的想法。

一、不匹配的整形转换代码

#include <stdio.h>
#define PAGES 336
#define WORDS 65618

int main(void)
{
	short num = PAGES;
	short mnum = -PAGES;
	int num2 = WORDS;
	int mnum2 = -WORDS;
	
	printf("num as short and unsigned short:%hd, %hu\n",num,num);
	printf("-num as short and unsigned short:%hd, %hu\n", mnum, mnum);
	printf("-WORDS as int and unsigned int:%d, %u\n", mnum2, mnum2);
	printf("-WORDS as short and unsigned short:%hd, %hu\n", mnum2, mnum2);
	printf("-WORDS as signed char and unsigned char:%hhd, %hhu\n", mnum2, mnum2);

	return 0;
}

二、该代码对应的输出结果的截图

三、基于机器码这样更偏底层的角度来分析

稍微接触过计算机的同学应该都知道,计算机中的数据都是用0、1这样的二进制码表示的,关于数字的表示大家也都有学过原码、反码、补码,在此都不再赘述。但是有两点需要强调:第一,原码的存在是为了让我们人脑计算该二进制码所代表的十进制数;第二,反码的存在是为了机器内部来存储、运算数据。这2点非常重要,接下来我们就基于这2点从更底层的角度来分析上述代码的结果。

PAGES对应的原码  00000000 00000000 00000001 01010000
-PAGES对应的原码 10000000 00000000 00000001 01010000
-WORDS对应的原码 10000000 00000001 00000000 01010010

PAGES对应的补码  00000000 00000000 00000001 01010000
-PAGES对应的补码 11111111 11111111 11111110 10110000
-WORDS对应的补码 11111111 11111110 11111111 10101110

如上由于PAGES \ WORDS 都是signed int类型的(-PAGES \ -WORDS同理),都占有4个字节(对C语言来说不同的系统int类型占用的字节数略有差异,此处默认与我的系统一样均为4个字节)。我们可以根据这两个常量对应的值,用程序员模式的计算器算出其原码,然后根据正数、负数中原码与补码的关系求出其对应的补码(如上已列出)。

由于short类型在我的系统中是2个字节,所以num在计算机内部的补码是PAGES对应补码的后两个字节,即为00000001 01010000。由于num是signed short类型的正数,所以num as short and unsigned short对应的原码都与补码一致,即 00000001 01010000,对应的十进制数即为336

mnum(即-num)在计算机内部的补码是-PAGES对应补码的后两个字节,即11111110 10110000。signed short是带符号的,第一位是符号位,该符号位上是1代表负号,所以-num as short对应的原码是 10000001 01010000,对应的十进制数即为-336;而unsigned short是不带符号的,都是正数,而正数的原码与机器内存储的补码相同,所以as unsigned short对应的原码是  11111110 10110000,对应的十进制数即为65200

与-PAGES类似,-WORDS as int对应的原码是 10000000 00000001 00000000 01010010,对应的十进制数即为-65618,as unsigned int对应的原码是 11111111 11111110 11111111 10101110,对应的十进制数即为4294901678

与-num类似,-WORDS as short对应的补码是11111111 10101110,所以原码是 10000000 01010010,对应的十进制数即为-82,as unsigned short对应的原码是 11111111 10101110,对应的十进制数即为65454

同理,-WORDS as signed char对应的补码是10101110,所以原码是 11010010,对应的十进制数即为-82, as unsigned char对应的原码是 10101110,对应的十进制数即为174

四、关于此种分析思路的一点想法

此分析思路的优点非常明显,无需死记不匹配的整形转换的规律,只需知道原码和反码的本质即可根据这一思路分析出结果。不过值得注意的是,C语言在不同的系统中,各个整数类型所占的字节数可能会略有差异。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值