C语言中汇编基础知识
我正在学习谭好强的《C程序设计》,学到第三章数据结构方面的了,可是里面讲了一些关于变量,常量在内存中贮存的结构,是按照补码的形式储存的。能不能解释一下什么是补码?还有一些...
我正在学习谭好强的《C程序设计》,学到第三章数据结构方面的了,可是里面讲了一些关于变量,常量在内存中贮存的结构,是按照补码的形式储存的。
能不能解释一下什么是补码?
还有一些什么“最高位为符号位”。。。这些话是什么意思?
最高位是指什么?符号位是指什么?
比如有这么一段二进制代码:000000001101
他说第一位的是符号位?为什么?
能不能再具体说一下10进制转8进制转16进制转2进制的运算过程?就是比如说把10进制的15依次转8,16和2进制的运算过程。
最好能一步步写详细点,并且每一步都带解释。 展开
能不能解释一下什么是补码?
还有一些什么“最高位为符号位”。。。这些话是什么意思?
最高位是指什么?符号位是指什么?
比如有这么一段二进制代码:000000001101
他说第一位的是符号位?为什么?
能不能再具体说一下10进制转8进制转16进制转2进制的运算过程?就是比如说把10进制的15依次转8,16和2进制的运算过程。
最好能一步步写详细点,并且每一步都带解释。 展开
4个回答
展开全部
C语言程序设计中关于补码的几个问题的探讨
摘 要:在C语言程序设计教学过程中,根据Turbo C中整型数据类型在内存中的存储形式为补码的特点,巧妙引进补码的定义公式,灵活、简单地解决了初学者难以理解的整型数据取值范围的来源、有符号与无符号类型之间自动转换时输出真值的判定问题,以及在使用求反运算符时如何确定输出真值的问题。在实际教学过程中,通过引进补码的概念及其定义公式,使学生迅速领会了这些问题的本质。
关键词:C语言;程序设计;补 码;位运算
1、引言
随着信息技术的发展和计算机知识的普及应用,现在大部分高校都在开设计算机程序设计课程,尤其是在各个高校的低年级当中开设具有高级语言和低级语言双重特性的C语言。而且,C语言也是学生进一步学习高级程序设计、数据结构和编译原理等课程的基础,是进一步学习深造的敲门砖,因此,各高校对C语言的教学也越来越重视。[1]但是,笔者在教学的过程当中发现学生对于整型数据表示范围的真正来历以及位运算中的求反运算在Turbo C中运行的结果难以理解。而补码可以担当解释C语言程序设计中这些问题的重要角色,用它可以以追根溯源的形式揭开它们在内存中的真正面目,使学生既加深对补码的认识又真正领会这些问题的本质。
2、原码、反码、补码
在描述问题之前,我们先看看原码、反码、补码的有关定义。另外,这里只针对Turbo C中整型数据类型来加以讨论。
(1)原码表示法
原码表示是一种比较直观的机器数的表示方法:约定数码序列中的最高位为符号位,符号位为0表示该数为正,为1表示该数为负,其余有效数值部分则用二进制的绝对值表示。而且,原码定点整数表示的范围为:-(2n-1)~2n-1。[2]
(2)反码表示法
正数的原码与反码相同,负数的反码为正数的数码序列中除去最高位以外所有位逐位取反,即二进制编码序列中0变为1,1变为0。
(3)补码表示法
补码表示方法是:如果为正数,则原码与补码的表示形式相同;如果数为负,则将负数原码除符号位外其余各位取反,末位加1,即得负数的补码。而且,对于定点整数X(其补码表示的范围为-2n~2n-1)[2],数X的补码记作 ,当机器字长为n时,补码定义如公式(1-1):
另外,在原码、反码、补码相互转换的规则中,可以遵循这样的规则:反码的反码是原码,补码的补码是原码。
3、整型数据类型取值范围的确定
在Turbo C当中(这里所用的Turbo C为Borland International ,inc.的Turbo C,Version 2.01),整型类型分为有符号和无符号两类。其中有符号的有分为short、int、long三种,用sizeof运算符可以求出它们各自在内存中所占存储空间分别为2字节、2字节、4个字节;无符号也分为unsigned short、unsigned int、unsigned long三种,各自在内存中所占存储空间分别为2字节、2字节、4个字节。另外,Turbo C当中整型数在内存在是以补码的形式存储的。那么,下面我们讨论大多数教材(这里以文献[3]为例)当中int型取值范围-32768~32767的来历及有符号与无符号之间数据类型自动转换所得结果的确定。
对于int类型,由于我们知道原码定点整数表示的范围为:-2n~2n-1,即-32767~32767,通过原码到补码的简单转换便可得知这些数据在内存中的实际存储方式。而对于-32768,超出了原码定点整数表示的范围-32767~32767,那么,对于初学者来说,这个-32768就像是无中生有的数,捉摸不透。由于整型数在内存在中是以二进制补码的形式存储的,那么,我们可以借助公式(1-1)来求出-32768的补码,进而写出它在内存中的二进制形式。根据公式(1-1)我们可以得到 ,其二进制形式为1000 0000 0000 0000,即十进制的215,根据2中介绍的“补码的补码是原码”的规则可知其反码为1111 1111 1111 1111,其原码为1000 0000 0000 0000(所进高位被丢弃,符号位不变),由于原码中-0(1000 0000 0000 0000)和+0(0000 0000 0000 0000)在内存中的表示形式统一为0000 0000 0000 0000(补码)(具体参见文献[3]Page257),因而,可以理解为-32768占用-0的存储空间。而且,在实际应用当中,由于整型数是以补码的形式而存储于内存中,所以,只需按照公式(1-1)求出该数的补码便可得知其在内存中的存储方式而大可不必追究其原码的表示形式(因为,我们关注的重点是一个数在内存中的存储方式)。另外,利用公式(1-1)求出一个数的补码之后,同时也解决了有符号向无符号(或无符号向有符号)自动转换时输出结果的确定问题,考察例子Exa1,程序段如下:
Exa1 : int num=-32768;
unsigned num1=32768,num2=65535;
printf(“unsigned num =%u\n”,num);
printf(“signed num1=%d\n”,num1);
printf(“signed num2=%d”,num2);
初学者可能认为unsigned型的表示范围为0-65535,而判定在Turbo C环境下输出结果为一随机整数。其实我们按照公式(1-1)求出num表示的补码,然后写出其在内存中存储的二进制形式1000 0000 0000 0000,显然它没有超出范围而表示无符号整型中的32768。同理,对于无符号整型变量num1,可以知道其在内存中的存储形式为1000 0000 0000 0000,当转换为有符号输出时,则最高位1表示该数为负数(负数的符号位为1,因为按照2中有关原码、反码、补码的转换规则,原码转换到补码的过程中,符号位不变,而正数的补码的最高位始终为0),根据公式(1-1)可以反过来求出数 ,即输出结果为-32768;同理,对于无符号整型变量num2,可以知道其在内存中的存储形式为1111 1111 1111 1111,当转换为有符号输出时,则最高位1表示该数为负数,根据公式(1-1)可以反过来求出数 ,即输出结果为-1。同样地,对于其它几种整型类型取值范围也可按此来推理。
4、 求反运算符(~)的应用
~是一个单目运算符,用来对一个二进制数按位取反。这里有两点值得初学者注意,一是:~的操作数只能是整型或字符型的数据,它们在内存中都是以补码的形式存储的,二是:求反运算符会对内存中存储的补码的包括最高位在内的所有位按位取反,而且,求出的反码表示的也是内存中存储的二进制补码。考察例子Exa2
摘 要:在C语言程序设计教学过程中,根据Turbo C中整型数据类型在内存中的存储形式为补码的特点,巧妙引进补码的定义公式,灵活、简单地解决了初学者难以理解的整型数据取值范围的来源、有符号与无符号类型之间自动转换时输出真值的判定问题,以及在使用求反运算符时如何确定输出真值的问题。在实际教学过程中,通过引进补码的概念及其定义公式,使学生迅速领会了这些问题的本质。
关键词:C语言;程序设计;补 码;位运算
1、引言
随着信息技术的发展和计算机知识的普及应用,现在大部分高校都在开设计算机程序设计课程,尤其是在各个高校的低年级当中开设具有高级语言和低级语言双重特性的C语言。而且,C语言也是学生进一步学习高级程序设计、数据结构和编译原理等课程的基础,是进一步学习深造的敲门砖,因此,各高校对C语言的教学也越来越重视。[1]但是,笔者在教学的过程当中发现学生对于整型数据表示范围的真正来历以及位运算中的求反运算在Turbo C中运行的结果难以理解。而补码可以担当解释C语言程序设计中这些问题的重要角色,用它可以以追根溯源的形式揭开它们在内存中的真正面目,使学生既加深对补码的认识又真正领会这些问题的本质。
2、原码、反码、补码
在描述问题之前,我们先看看原码、反码、补码的有关定义。另外,这里只针对Turbo C中整型数据类型来加以讨论。
(1)原码表示法
原码表示是一种比较直观的机器数的表示方法:约定数码序列中的最高位为符号位,符号位为0表示该数为正,为1表示该数为负,其余有效数值部分则用二进制的绝对值表示。而且,原码定点整数表示的范围为:-(2n-1)~2n-1。[2]
(2)反码表示法
正数的原码与反码相同,负数的反码为正数的数码序列中除去最高位以外所有位逐位取反,即二进制编码序列中0变为1,1变为0。
(3)补码表示法
补码表示方法是:如果为正数,则原码与补码的表示形式相同;如果数为负,则将负数原码除符号位外其余各位取反,末位加1,即得负数的补码。而且,对于定点整数X(其补码表示的范围为-2n~2n-1)[2],数X的补码记作 ,当机器字长为n时,补码定义如公式(1-1):
另外,在原码、反码、补码相互转换的规则中,可以遵循这样的规则:反码的反码是原码,补码的补码是原码。
3、整型数据类型取值范围的确定
在Turbo C当中(这里所用的Turbo C为Borland International ,inc.的Turbo C,Version 2.01),整型类型分为有符号和无符号两类。其中有符号的有分为short、int、long三种,用sizeof运算符可以求出它们各自在内存中所占存储空间分别为2字节、2字节、4个字节;无符号也分为unsigned short、unsigned int、unsigned long三种,各自在内存中所占存储空间分别为2字节、2字节、4个字节。另外,Turbo C当中整型数在内存在是以补码的形式存储的。那么,下面我们讨论大多数教材(这里以文献[3]为例)当中int型取值范围-32768~32767的来历及有符号与无符号之间数据类型自动转换所得结果的确定。
对于int类型,由于我们知道原码定点整数表示的范围为:-2n~2n-1,即-32767~32767,通过原码到补码的简单转换便可得知这些数据在内存中的实际存储方式。而对于-32768,超出了原码定点整数表示的范围-32767~32767,那么,对于初学者来说,这个-32768就像是无中生有的数,捉摸不透。由于整型数在内存在中是以二进制补码的形式存储的,那么,我们可以借助公式(1-1)来求出-32768的补码,进而写出它在内存中的二进制形式。根据公式(1-1)我们可以得到 ,其二进制形式为1000 0000 0000 0000,即十进制的215,根据2中介绍的“补码的补码是原码”的规则可知其反码为1111 1111 1111 1111,其原码为1000 0000 0000 0000(所进高位被丢弃,符号位不变),由于原码中-0(1000 0000 0000 0000)和+0(0000 0000 0000 0000)在内存中的表示形式统一为0000 0000 0000 0000(补码)(具体参见文献[3]Page257),因而,可以理解为-32768占用-0的存储空间。而且,在实际应用当中,由于整型数是以补码的形式而存储于内存中,所以,只需按照公式(1-1)求出该数的补码便可得知其在内存中的存储方式而大可不必追究其原码的表示形式(因为,我们关注的重点是一个数在内存中的存储方式)。另外,利用公式(1-1)求出一个数的补码之后,同时也解决了有符号向无符号(或无符号向有符号)自动转换时输出结果的确定问题,考察例子Exa1,程序段如下:
Exa1 : int num=-32768;
unsigned num1=32768,num2=65535;
printf(“unsigned num =%u\n”,num);
printf(“signed num1=%d\n”,num1);
printf(“signed num2=%d”,num2);
初学者可能认为unsigned型的表示范围为0-65535,而判定在Turbo C环境下输出结果为一随机整数。其实我们按照公式(1-1)求出num表示的补码,然后写出其在内存中存储的二进制形式1000 0000 0000 0000,显然它没有超出范围而表示无符号整型中的32768。同理,对于无符号整型变量num1,可以知道其在内存中的存储形式为1000 0000 0000 0000,当转换为有符号输出时,则最高位1表示该数为负数(负数的符号位为1,因为按照2中有关原码、反码、补码的转换规则,原码转换到补码的过程中,符号位不变,而正数的补码的最高位始终为0),根据公式(1-1)可以反过来求出数 ,即输出结果为-32768;同理,对于无符号整型变量num2,可以知道其在内存中的存储形式为1111 1111 1111 1111,当转换为有符号输出时,则最高位1表示该数为负数,根据公式(1-1)可以反过来求出数 ,即输出结果为-1。同样地,对于其它几种整型类型取值范围也可按此来推理。
4、 求反运算符(~)的应用
~是一个单目运算符,用来对一个二进制数按位取反。这里有两点值得初学者注意,一是:~的操作数只能是整型或字符型的数据,它们在内存中都是以补码的形式存储的,二是:求反运算符会对内存中存储的补码的包括最高位在内的所有位按位取反,而且,求出的反码表示的也是内存中存储的二进制补码。考察例子Exa2
展开全部
计算机里存贮数都是用补码的形式。正数和0的补码永远都是自己,负数的补码就是它的绝对值按位取反,加1。
负数的补码就是对反码加一,而正数不变,正数的原码反码补码是一样的.在补码中用(-128)代替了(-0),所以补码的表示范围为:
(-128~0~127)共256个.
注意:(-128)没有相对应的原码和反码, (-128) = (10000000) 补码的加减运算如下:
( 1 ) 10- ( 1 ) 10= ( 1 )10 + ( -1 )10 = ( 0 )10
(00000001)补 + (11111111)补 = (00000000)补 = ( 0 ) 正确
( 1 ) 10- ( 2) 10= ( 1 )10 + ( -2 )10 = ( -1 )10
(00000001) 补+ (11111110) 补= (11111111)补 = ( -1 ) 正确
所以补码的设计目的是:
⑴使符号位能与有效值部分一起参加运算,从而简化运算规则.
⑵使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计
[0]补=00000000b
[1]补=00000001b
[2]补=00000010b
[3]补=00000011b
----------------
[-0]补=00000000b
[-1]补=11111111b(注:-1的绝对值为1,按位取反后为11111110b,加1就得到了-1的补码:11111111b)
[-2]补=11111110b
[-3]补=11111101b
负数的补码就是对反码加一,而正数不变,正数的原码反码补码是一样的.在补码中用(-128)代替了(-0),所以补码的表示范围为:
(-128~0~127)共256个.
注意:(-128)没有相对应的原码和反码, (-128) = (10000000) 补码的加减运算如下:
( 1 ) 10- ( 1 ) 10= ( 1 )10 + ( -1 )10 = ( 0 )10
(00000001)补 + (11111111)补 = (00000000)补 = ( 0 ) 正确
( 1 ) 10- ( 2) 10= ( 1 )10 + ( -2 )10 = ( -1 )10
(00000001) 补+ (11111110) 补= (11111111)补 = ( -1 ) 正确
所以补码的设计目的是:
⑴使符号位能与有效值部分一起参加运算,从而简化运算规则.
⑵使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计
[0]补=00000000b
[1]补=00000001b
[2]补=00000010b
[3]补=00000011b
----------------
[-0]补=00000000b
[-1]补=11111111b(注:-1的绝对值为1,按位取反后为11111110b,加1就得到了-1的补码:11111111b)
[-2]补=11111110b
[-3]补=11111101b
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
补码的具体定义及解释。网上一搜就搜得到。
我只会一个十进制负数转二进制的方法。里面涉及到了补码,最高位。
比如说-4.
4的二进制形式是100
前面补零
就是0000 0000 0000 0100
最高位是左边第1位。
因为是负数。最高位就要反过来。变成1
则原式 1000 0000 0000 0100
第一位为符号位为什么。这个具体的解释我也不能说明白。只能说到这样了 。
不懂的话可以到网上去查
我只会一个十进制负数转二进制的方法。里面涉及到了补码,最高位。
比如说-4.
4的二进制形式是100
前面补零
就是0000 0000 0000 0100
最高位是左边第1位。
因为是负数。最高位就要反过来。变成1
则原式 1000 0000 0000 0100
第一位为符号位为什么。这个具体的解释我也不能说明白。只能说到这样了 。
不懂的话可以到网上去查
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询