4.1这是个有类型的世界 4.2数据类型基本概念 4.2.1理解数据类型 4.2.2理解整型和实型 4.2.3理解数值的范围 4.2.4理解有符号数和无符号数 4.3字符集和保留字 4.3.1字符集 4.3.2保留字 4.4基本数据类型 4.4.1字符型和各种整型、实型 4.4.2布尔型(boo1)和无类型(void) 4.4.3为数据类型起别名: typedef 4.5 sizeof的使用 4.5.1 sizeof例程 4.1这是个有类型的世界 问大家一个问题 现实生活,有哪些信息可以用计算机可以管理呢? 职工、学员、客户、工资、原材料、产品、商品……现实中实现用计算机管理的信息已 是无数 职工又有什么信息呢? 职工有姓名、性别、出生年月、家庭住址、电话,婚否、工龄、工种、工资、等等 这两个问题你可能回答得不错,现在,考验你前几章有没有认真学习的时刻到了,请看 下面这个问题 所有的这些信息,在计算机里都是以什么样的数据形式来表达呢?请自觉闭上眼睛,想 一想。再看以下的各种回答
4.1 这是个有类型的世界 4.2 数据类型基本概念 4.2.1 理解数据类型 4.2.2 理解整型和实型 4.2.3 理解数值的范围 4.2.4 理解有符号数和无符号数 4.3 字符集和保留字 4.3.1 字符集 4.3.2 保留字 4.4 基本数据类型 4.4.1 字符型和各种整型、实型 4.4.2 布尔型(bool)和无类型(void) 4.4.3 为数据类型起别名:typedef 4.5 sizeof 的使用 4.5.1 sizeof 例程 4.1 这是个有类型的世界 问大家一个问题: 现实生活,有哪些信息可以用计算机可以管理呢? 职工、学员、客户、工资、原材料、产品、商品……现实中实现用计算机管理的信息已 是无数。 职工又有什么信息呢? 职工有姓名、性别、出生年月、家庭住址、电话,婚否、工龄、工种、工资、等等。 这两个问题你可能回答得不错,现在,考验你前几章有没有认真学习的时刻到了,请看 下面这个问题: 所有的这些信息,在计算机里都是以什么样的数据形式来表达呢?请自觉闭上眼睛,想 一想。再看以下的各种回答
“二进数”,正确 已数字化的数据”,也算正确 “0和1”,正确, “机器语言”,正确,你还记得第一章的内容啊,不错。 本章需要继续的一个问题就由此开始。所有的信息都用机器语言一一那些0和1——表 达,那你我编写程序岂不很难? 这是第一章的问题,你还记得在第一章关于本问题回答吗?那就是:机器语言不好记, 那就用高级语言。高级语言高级在哪里呢?第一章也有答案:就高级在它尽量向“高级动 物”的思维习惯做了一些接近。当然,只能说尽量,它必须仍然保持符合机器的绝大部分 特点,否则,大家就不要学计算机语言了 数据类型,就是计算机语言向人类语言靠近时,走出的第一步,很重要的一步。(机器 语言或汇编语里,没有数据类型一说。) 人类的世界,是有类型的世界 树木花草,归一类:植物 猪狗猫羊,动物 金银铜铁,金属 你我他她,人类。(不要告诉我你不是人类,在这虚拟的网络的世界…… 上一章笔者“鼓吹”过一个观点:整个世界都可以用数据和处理来表达。基于此,整个 世界就是一个程序:而万物是世界的数据。如果你找一个人,对他说:“你等于一只猪 他一定暴跳如雷。为什么呢?嘻嘻,学了这一章,我们就可以从程序的角度来解释了:人 和猪不是一类型,不适于做赋值操作。待以后我们学了C++的“类”,则又有更好回答:上 帝创造世界是,没有为人“类”实现参数为猪“类”的拷贝构造函数,或等号重载函数。 (想和上帝做同行?快做个程序员。) 4.2数据类型基本概念 4.2.1理解数据类型
“二进数”,正确。 “已数字化的数据”,也算正确。 “0 和 1”,正确。 “机器语言”,正确,你还记得第一章的内容啊,不错。 本章需要继续的一个问题就由此开始。所有的信息都用机器语言——那些 0 和 1——表 达,那你我编写程序岂不很难? 这是第一章的问题,你还记得在第一章关于本问题回答吗?那就是:机器语言不好记, 那就用高级语言。高级语言高级在哪里呢?第一章也有答案:就高级在它尽量向“高级动 物”的思维习惯做了一些接近。当然,只能说尽量,它必须仍然保持符合机器的绝大部分 特点,否则,大家就不要学计算机语言了。 数据类型,就是计算机语言向人类语言靠近时,走出的第一步,很重要的一步。(机器 语言或汇编语里,没有数据类型一说。) 人类的世界,是有类型的世界。 树木花草,归一类:植物; 猪狗猫羊,动物; 金银铜铁,金属; 你我他她,人类。(不要告诉我你不是人类,在这虚拟的网络的世界……) 上一章笔者“鼓吹”过一个观点:整个世界都可以用数据和处理来表达。基于此,整个 世界就是一个程序;而万物是世界的数据。如果你找一个人,对他说:“你等于一只猪”, 他一定暴跳如雷。为什么呢?嘻嘻,学了这一章,我们就可以从程序的角度来解释了:人 和猪不是一类型,不适于做赋值操作。待以后我们学了 C++的“类”,则又有更好回答:上 帝创造世界是,没有为人“类”实现参数为猪“类”的拷贝构造函数,或等号重载函数。 (想和上帝做同行?快做个程序员。) 4.2 数据类型基本概念 4.2.1 理解数据类型
“数据类型”就是这么一个很好理解的概念。我们的重点是了解在计算机编程世界中 有哪些基本的数据类型?在人类世界里,数据类型那就多了,把人类的对万物划分类型的 方法照搬入计算机世界,显然不可能。怎么办呢?方法就是:抽象。 计算机先哲们为我们做了这一切。其中,最重要类型,也称为C/C++语言的基本数据类 型,只有两个:“数值 第一是“数值类型”。这样,在职工的信息中,譬如年纪,工龄、工资就有了归属。你 现在需要暂时不将目光从屏幕前移开,想一想“数值类型”是一个多好的抽象结果!无论 进行任何信息管理,离开了“数”,还能管理什么? 第二是“字符类型”。像职工姓名或家庭住址,这些由字符类型的数据组成。你可能想 不到的还有,职工的电话号码010-1234567,这也是由字符类型数据组成。0、1、2、3不 是数字吗?应该属于上面的“数值”类型吧?嗯,你听我说:现实生活中,数字被广泛地 应用在两种不同范畴:其一是那些典型的,需要进行计算的场合。比如鸡蛋1斤2.3元: 其二则那些只用来表示符号的范畴。比如电话号码,比如车牌号。把两个电话号码进行相 加或相减的操作是没有意义的。基于数字的两种完全不一样的使用范畴,所以在被抽象到 计算机程序语言时,数字被分到“数值”和“字符”两种类型中。但字符类型并不只有阿 拉伯数字,键盘上的字母符号,都属于字符类型。 在C/C+中,“字符类型”其实也可归入数值类型。在某些情况下,它仍然会被用来参 与计算。比如在计算机中,字符‘A’加1后,会得到下一个字符‘B’,这种操作符合我 们的习惯 4.2.2理解整型和实型 数值类型又被分为“整型”和“实型”。整型就是不带小数位的数,而实型则是指带小 数位的数,也称为“浮点数”。我们在生活中一般并不做如此区分。譬如说鸡蛋的价格罢 今儿便宜了,一斤2块整,但这不防碍明儿价涨了,我们说成:涨了,2.30元一斤。在编 程时可不能这样,你必须事先考虑到鸡蛋的价格是必须带小数的,就算现在是2块整,也 得将价格定为实型,否则,涨成2块3时,计算机会把那0.3元给丢了,还是变成2元整
“数据类型”就是这么一个很好理解的概念。我们的重点是了解在计算机编程世界中, 有哪些基本的数据类型?在人类世界里,数据类型那就多了,把人类的对万物划分类型的 方法照搬入计算机世界,显然不可能。怎么办呢?方法就是:抽象。 计算机先哲们为我们做了这一切。其中,最重要类型,也称为 C/C++语言的基本数据类 型,只有两个:“数值”和“字符”。 第一是“数值类型”。这样,在职工的信息中,譬如年纪,工龄、工资就有了归属。你 现在需要暂时不将目光从屏幕前移开,想一想“数值类型”是一个多好的抽象结果!无论 进行任何信息管理,离开了“数”,还能管理什么? 第二是“字符类型”。像职工姓名或家庭住址,这些由字符类型的数据组成。你可能想 不到的还有,职工的电话号码 010-1234567,这也是由字符类型数据组成。0、1、2、3 不 是数字吗?应该属于上面的“数值”类型吧?嗯,你听我说:现实生活中,数字被广泛地 应用在两种不同范畴:其一是那些典型的,需要进行计算的场合。比如鸡蛋 1 斤 2.3 元; 其二则那些只用来表示符号的范畴。比如电话号码,比如车牌号。把两个电话号码进行相 加或相减的操作是没有意义的。基于数字的两种完全不一样的使用范畴,所以在被抽象到 计算机程序语言时,数字被分到“数值”和“字符”两种类型中。但字符类型并不只有阿 拉伯数字,键盘上的字母符号,都属于字符类型。 在 C/C++中,“字符类型”其实也可归入数值类型。在某些情况下,它仍然会被用来参 与计算。比如在计算机中,字符‘A’加 1 后,会得到下一个字符‘B’,这种操作符合我 们的习惯。 4.2.2 理解整型和实型 数值类型又被分为“整型”和“实型”。整型就是不带小数位的数,而实型则是指带小 数位的数,也称为“浮点数”。我们在生活中一般并不做如此区分。譬如说鸡蛋的价格罢, 今儿便宜了,一斤 2 块整,但这不防碍明儿价涨了,我们说成:涨了,2.30 元一斤。在编 程时可不能这样,你必须事先考虑到鸡蛋的价格是必须带小数的,就算现在是 2 块整,也 得将价格定为实型,否则,涨成 2 块 3 时,计算机会把那 0.3 元给丢了,还是变成 2 元整
你会问为什么不直接就定一个实型就好呢?实型不就包含了整型的值吗(如2.0等于2 元)?好!问得好,我不喜欢书上说什么就记什么,一个“为什么”也不去想的学习方法 由于能力的限制,大多数人如你我,都不能为这个世界发明奉献什么新技术,我们只能作 为技术的“接受者”而活在这个世上。然而正因为只能作为接受者,我们就更应该在学习 任何技术前,先学会从一定的高度来询问:为什么会有这个技术(这个技术为什么会出现)? 我现在需要这个技术吗(必竟学习需要占用时间)?这么做并非是一种消极态度,相反 它的积极意议在于:经过这种思考,你不仅可以把有限的时间花在值的学习上,而且只有 弄明白了一样技术(或技术的概念)产生的需要,我们才有可能真正理解它,从而比别人 学得更深刻更本质 一个问题牵出一堆废话,回答却很简单:因为在计算机里,对整数的运算要远远快于对 浮点数的运算,所以,在人类的思维习惯与计算机特点之间,必须做一个折衷。 折衷的结果就是虽然都是数值类型,但程序员在程序时,必须事先想好,哪些数据是必 须带小数计算的,那些数据定为实型,比如工资,没有哪个员工会认为老板可以将自已工 资中的小数位忽略不计;而那些可以不用,或者可以不计较小数的数值,则被建议设计成 整型,比如人的年纪,虽然可以,但我们很少需要有类似1.6岁这种说法。想想,假如 位女士说自已28岁,而你却立刻纠正她:“不,准确地说,您已经28.7岁了”……结局 会怎样呢?为了那0.7岁,不仅你的程序会跑得慢,而且会倍受女人的白眼杀伤。 想想其实也很自然:工资必须设计成实型,而年龄虽然不是必须,但建议设计成整型。 4.2.3理解数值的范围 然而事情并未就此结束。 顾及计算机的运行速度,人(程序员)做出了妥协,必须面对“整型”或“实型”的考 虑。另一方面,和速度同样重要的是计算机的空间的考虑。它让程序员必须再做一步妥协 小时候你一定有过这样的经历:你说100,另一个小伙伴就说101。你说1000,他就说 1001,你说10000,他就说:那我10001。总之他就是要比你大1。这种游戏不会有分出胜 负的结局,只会让你郁闷为什么就不能有个最大数让你说了以后,那家伙就再了无法往上 加1了!现在你学编程,儿时的“妄想”终于在计算机的世界中实现了。在计算机世界中, 你可以说一个数,当别人再住这个数加1时,真不幸,计算机会告诉他说:加1是加1了 可是结果变成0,甚至是负数
你会问为什么不直接就定一个实型就好呢?实型不就包含了整型的值吗(如 2.0 等于 2 元)?好!问得好,我不喜欢书上说什么就记什么,一个“为什么”也不去想的学习方法。 由于能力的限制,大多数人如你我,都不能为这个世界发明奉献什么新技术,我们只能作 为技术的“接受者”而活在这个世上。然而正因为只能作为接受者,我们就更应该在学习 任何技术前,先学会从一定的高度来询问:为什么会有这个技术(这个技术为什么会出现)? 我现在需要这个技术吗(必竟学习需要占用时间)?这么做并非是一种消极态度,相反, 它的积极意议在于:经过这种思考,你不仅可以把有限的时间花在值的学习上,而且只有 弄明白了一样技术(或技术的概念)产生的需要,我们才有可能真正理解它,从而比别人 学得更深刻更本质。 一个问题牵出一堆废话,回答却很简单:因为在计算机里,对整数的运算要远远快于对 浮点数的运算,所以,在人类的思维习惯与计算机特点之间,必须做一个折衷。 折衷的结果就是虽然都是数值类型,但程序员在程序时,必须事先想好,哪些数据是必 须带小数计算的,那些数据定为实型,比如工资,没有哪个员工会认为老板可以将自已工 资中的小数位忽略不计;而那些可以不用,或者可以不计较小数的数值,则被建议设计成 整型,比如人的年纪,虽然可以,但我们很少需要有类似 1.6 岁这种说法。想想,假如一 位女士说自已 28 岁,而你却立刻纠正她:“不,准确地说,您已经 28.7 岁了”……结局 会怎样呢?为了那 0.7 岁,不仅你的程序会跑得慢,而且会倍受女人的白眼杀伤。 想想其实也很自然:工资必须设计成实型,而年龄虽然不是必须,但建议设计成整型。 4.2.3 理解数值的范围 然而事情并未就此结束。 顾及计算机的运行速度,人(程序员)做出了妥协,必须面对“整型”或“实型”的考 虑。另一方面,和速度同样重要的是计算机的空间的考虑。它让程序员必须再做一步妥协。 小时候你一定有过这样的经历:你说 100,另一个小伙伴就说 101。你说 1000,他就说 1001,你说 10000,他就说:那我 10001。总之他就是要比你大 1。这种游戏不会有分出胜 负的结局,只会让你郁闷为什么就不能有个最大数让你说了以后,那家伙就再了无法往上 加 1 了!现在你学编程,儿时的“妄想”终于在计算机的世界中实现了。在计算机世界中, 你可以说一个数,当别人再住这个数加 1 时,真不幸,计算机会告诉他说:加 1 是加 1 了, 可是结果变成 0,甚至是负数
这就是计算机的空间问题:任何一个量,都有一个大的上限,和小的下限,出了这个范 围(比上限还大,比下限还小),就会称为溢出。这是一种物理的现实,也是一种人为的 规定。为什么要这样规定?原因是计算机的存储器,特别是其中很重要的内存(见上章), 其可存储的数据多少总是有限度。(而且,同样大小数,2进制的表达形式比10进制长得 多),如果允许编程像生活中一样任何一个数都可以很大很大,也就是这个量表达起来将 很长很长,那么存储器的空间就会很快用完!(无穷大就不用说了,因为不可能有无穷大 的存储器)。 就是这样,数值类型在被划分为整型和实型后,将根据所占用的空间而被继续划分为几 种不同类型。而我们,在考虑工资必须设计成带小数的实型后,必须再面对一个设计上的 考虑,工资这个量在程序里要占多大空间?依据其实很简单,就看你的单位最高月薪是多 少,凭此找到一个合适的类型。比如月薪不超过1万元,那我们选择一个刚刚可以包含10000 的数据类型 两种基础类型:数值类型和字符类型,前者说了很多,现在我们也来对字符类型做一些 附加说明。字符类型要比数值类型简单得多:它不能带小数,所以没有整型实型之说。它 占用1个字节,已经是计算机能单独处理的最小空间单位,所以也不存在继续分为不同空 间长度的问题。因此,我们将以它为例,详细说明有关数据类型的一些基本而重要的概念。 第1、由于计算机和编程都是老外的发明,而老外生活中常用的的字符并不多一一主要 是阿拉伯数字、英文字母、标点符号等一一所以字符的宽度被定为1个字节(如果忘了什 么叫字节,请看上章) 1字节=8位,所以它能表示的最大数当然是8位都是1(既然2进制的数只能是0或 1,如果是我们常见的10进制,那就8位都为9,这样说,你该懂了? 1字节的二进制数中,最大的数:1111 这个数的大小是多少呢?让我们来把它转换为十进制数。 无论是什么进制,都是左边是高位,右边是低位。第一章中我们说过,10进制数的最低 位(个)位的权值是10°,第二位是10,第三位是102……,用小学课本上的说法就是:个 位上的数表示几个1,十位上的数表示向个10,百位上的数表示几个100… 二进制数则是:第1位数表示几个1(2),第2位数表示几个2(2),第3位数表 示几个4(2),第4位数表示向个8(2
这就是计算机的空间问题:任何一个量,都有一个大的上限,和小的下限,出了这个范 围(比上限还大,比下限还小),就会称为溢出。这是一种物理的现实,也是一种人为的 规定。为什么要这样规定?原因是计算机的存储器,特别是其中很重要的内存(见上章), 其可存储的数据多少总是有限度。(而且,同样大小数,2 进制的表达形式比 10 进制长得 多),如果允许编程像生活中一样任何一个数都可以很大很大,也就是这个量表达起来将 很长很长,那么存储器的空间就会很快用完!(无穷大就不用说了,因为不可能有无穷大 的存储器)。 就是这样,数值类型在被划分为整型和实型后,将根据所占用的空间而被继续划分为几 种不同类型。而我们,在考虑工资必须设计成带小数的实型后,必须再面对一个设计上的 考虑,工资这个量在程序里要占多大空间?依据其实很简单,就看你的单位最高月薪是多 少,凭此找到一个合适的类型。比如月薪不超过 1 万元,那我们选择一个刚刚可以包含 10000 的数据类型。 两种基础类型:数值类型和字符类型,前者说了很多,现在我们也来对字符类型做一些 附加说明。字符类型要比数值类型简单得多:它不能带小数,所以没有整型实型之说。它 占用 1 个字节,已经是计算机能单独处理的最小空间单位,所以也不存在继续分为不同空 间长度的问题。因此,我们将以它为例,详细说明有关数据类型的一些基本而重要的概念。 第 1、由于计算机和编程都是老外的发明,而老外生活中常用的的字符并不多——主要 是阿拉伯数字、英文字母、标点符号等——所以字符的宽度被定为 1 个字节(如果忘了什 么叫字节,请看上章)。 1 字节 = 8 位,所以它能表示的最大数当然是 8 位都是 1(既然 2 进制的数只能是 0 或 1,如果是我们常见的 10 进制,那就 8 位都为 9,这样说,你该懂了?)。 1 字节的二进制数中,最大的数:11111111。 这个数的大小是多少呢?让我们来把它转换为十进制数。 无论是什么进制,都是左边是高位,右边是低位。第一章中我们说过,10 进制数的最低 位(个)位的权值是 100,第二位是 101,第三位是 102……,用小学课本上的说法就是:个 位上的数表示几个 1,十位上的数表示向个 10,百位上的数表示几个 100…… 二进制数则是:第 1 位数表示几个 1 (2 0),第 2 位数表示几个 2(2 1),第 3 位数表 示几个 4(2 2),第 4 位数表示向个 8(2 3 )……
在C/C++中,很多计数的习惯都是从0开始,所以,在你看明白上面那行内容后,让我 们立刻改口换成下面的说法,以后我们只用这种说法 二进制数:第0位数表示几个1(20),第1位数表示几个2(2),第3位数表示几 个4(2),第4位数表示向个8(2)…… 按照这种说法,我们可以发现,从右向左数,第n位数的权值=2的n次方 进制各位权值的计算方法:第n位权值=2 下表详细地表示2进制数:1111111是如何逐位计算,累加得到10进制的值 25=3 合计 进制 l0进制 8 255 上表表示了这么一个计算过程*表示乘号): 1*22+1*26+1*25+1*24+1*23+1*2+1*24+1*2°=255 (顺便说一句,如果你忘了2等于多少有点迟疑,请复习一下初中的数学知识:任何数 的0次方都等于1) 结果是 111111255(d) (为不了互相混淆,我们在书中常用(b)来表示前面的数是2进制的,而(d)则表示该数 是10进制数。同样地,另有8进制数用(o)表示,16进制用(h)表示。不过记住了,这只是 在书中使用,在程序中,另有一套表示方法。) 以前我们知道1个字节有8位,现在通过计算,我们又得知:1个字节可以表达的最大的 数是255,也就是说表示0255这256个数。 那么两个字节(双字节数)呢?双字节共16位。111111个数并不大, 但长得有点眼晕,从现在起,我们要学会这样来表达二制数: 1111111111,即每4位隔一空格 双字节数最大值为 1*2+1*+1*2+ +1*2+1*2+ +1*2+1*2 2°=65535
在 C / C++中,很多计数的习惯都是从 0 开始,所以,在你看明白上面那行内容后,让我 们立刻改口换成下面的说法,以后我们只用这种说法: 二进制数:第 0 位数表示几个 1 (2 0),第 1 位数表示几个 2(2 1),第 3 位数表示几 个 4(2 2),第 4 位数表示向个 8(23 )…… 按照这种说法,我们可以发现,从右向左数,第 n 位数的权值 = 2 的 n 次方。 二进制各位权值的计算方法: 第 n 位权值 = 2n 下表详细地表示 2 进制数:11111111 是如何逐位计算,累加得到 10 进制的值: 第几位 7 6 5 4 3 2 1 0 权值 2 7=128 2 6=64 2 5=32 2 4=16 2 3=8 2 2=4 2 1=2 2 0=1 合计 2 进制 1 1 1 1 1 1 1 1 10 进制 128 64 32 16 8 4 2 1 255 上表表示了这么一个计算过程(*表示乘号): 1 * 27 + 1 * 26 + 1 * 25 + 1 * 24 + 1 * 23 + 1 * 22 + 1 * 21 + 1* 20 = 255 (顺便说一句,如果你忘了 2 0 等于多少有点迟疑,请复习一下初中的数学知识:任何数 的 0 次方都等于 1) 结果是: 11111111(b) = 255 (d) (为不了互相混淆,我们在书中常用(b)来表示前面的数是 2 进制的,而(d)则表示该数 是 10 进制数。同样地,另有 8 进制数用(o)表示,16 进制用(h)表示。不过记住了,这只是 在书中使用,在程序中,另有一套表示方法。) 以前我们知道 1 个字节有 8 位,现在通过计算,我们又得知:1 个字节可以表达的最大的 数是 255,也就是说表示 0~255 这 256 个数。 那么两个字节(双字节数)呢?双字节共 16 位。 1111111111111111,这个数并不大, 但长得有点眼晕,从现在起,我们要学会这样来表达二制数: 1111 1111 1111 1111,即每 4 位隔一空格。 双字节数最大值为: 1 * 215 + 1 *214 + 1* 213 + 1 * 212 + 1 * 211 + 1 * 210 + …… + 1 * 22 + 1 * 21 + 1* 2 0 = 65535
很自然,我们可以想到,一种数据类型允许的最大值,和它的位数有关。具体的计算方 法方法是,如果它有n位,那么最大值就是 n位二进制数的最大值:1*2(m)+1*2-2 +1*2° 任何一种基本数据类型,都有其范围。比如字符类型,它的最大值是255,那么,当一个 数在其类型的范围己经是最大值时,如果再往上加1,就会照成“溢出”。 其实,有限定的范围的数量,并不只在计算机中出现。钟表就是一个例子。10点再加1 点是11点,再加1点是12点,可是再加1点,就又回到1点。再如汽车的行程表,假设 最多只能显示99公里,当达到最高值后继续行驶,行程表就会显示为00000公里。 4.2.4理解有符号数和无符号数 回头看上一节,我们所讲的数都是正数。同样是年纪和工资,前者不需要有负值,但后 者可能需要一一至少所有的老板都这样认为 那么,负数在计算机中如何表示呢? 这一点,你可能听过两种不同的回答 种是教科书,它会告诉你:计算机用“补码”表示负数。可是有关“补码”的概念 说就得一节课,这一些我们需要在第6章中用一章的篇幅讲2进制的一切。再者,用“补 码”表示负数,其实一种公式,公式的作用在于告诉你,想得问题的答案,应该如何计算。 却并没有告诉你为什么用这个公式就可以和答案? 另一种是一些程序员告诉你的:用二进制数的最高位表示符号,最高位是0,表示正数, 最高位是1,表示负数。这种说法本身没错,可是如果没有下文,那么它就是错的。至少它 不能解释,为什么字符类型的-1用二进制表示是“1111111”(16进制为FF):而不是我 们更能理解的“10000001”。(为什么说后者更好理解呢?因为既然说最高位是1时表示 负数,那10000001不是正好是-1吗?) 让我们从头说起 1、你自已决定是否需要有正负 就像我们必须决定某个量使用整数还是实数,使用多大的范围数一样,我们必须自已决 定某个量是否需要正负。如果这个量不会有负值,那么我们可以定它为带正负的类型
很自然,我们可以想到,一种数据类型允许的最大值,和它的位数有关。具体的计算方 法方法是,如果它有 n 位,那么最大值就是: n 位二进制数的最大值:1 * 2(n-1) + 1 * 2(n-2) + . .. + 1 * 2 0 任何一种基本数据类型,都有其范围。比如字符类型,它的最大值是 255,那么,当一个 数在其类型的范围已经是最大值时,如果再往上加 1,就会照成“溢出”。 其实,有限定的范围的数量,并不只在计算机中出现。钟表就是一个例子。10 点再加 1 点是 11 点,再加 1 点是 12 点,可是再加 1 点,就又回到 1 点。再如汽车的行程表,假设 最多只能显示 99999 公里,当达到最高值后继续行驶,行程表就会显示为 00000 公里。 4.2.4 理解有符号数和无符号数 回头看上一节,我们所讲的数都是正数。同样是年纪和工资,前者不需要有负值,但后 者可能需要——至少所有的老板都这样认为。 那么,负数在计算机中如何表示呢? 这一点,你可能听过两种不同的回答。 一种是教科书,它会告诉你:计算机用“补码”表示负数。可是有关“补码”的概念一 说就得一节课,这一些我们需要在第 6 章中用一章的篇幅讲 2 进制的一切。再者,用“补 码”表示负数,其实一种公式,公式的作用在于告诉你,想得问题的答案,应该如何计算。 却并没有告诉你为什么用这个公式就可以和答案? 另一种是一些程序员告诉你的:用二进制数的最高位表示符号,最高位是 0,表示正数, 最高位是 1,表示负数。这种说法本身没错,可是如果没有下文,那么它就是错的。至少它 不能解释,为什么字符类型的-1 用二进制表示是“1111 1111”(16 进制为 FF);而不是我 们更能理解的“1000 0001”。(为什么说后者更好理解呢?因为既然说最高位是 1 时表示 负数,那 1000 0001 不是正好是-1 吗?)。 让我们从头说起。 1、你自已决定是否需要有正负。 就像我们必须决定某个量使用整数还是实数,使用多大的范围数一样,我们必须自已决 定某个量是否需要正负。如果这个量不会有负值,那么我们可以定它为带正负的类型
在计算机中,可以区分正负的类型,称为有符类型,无正负的类型(只有正值),称为 无符类型。 数值类型分为整型或实型,其中基型又分为无符类型或有符类型,而实型则只有符类型。 字符类型也分为有符和无符类型。 比如有两个量,年龄和库存,我们可以定前者为无符的字符类型,后者定为有符的整数 类 2、使用二制数中的最高位表示正负。 首先得知道最高位是哪一位?1个字节的类型,如字符类型,最高位是第7位,2个字 节的数,最高位是第15位,4个字节的数,最高位是第31位。不同长度的数值类型,其最 高位也就不同,但总是最左边的那位(如下示意)。字符类型固定是1个字节,所以最高 位总是第7位 (红色为最高位) 单字节数:1111111 双字节数:111111111111 四字节数:11111111111111111 当我们指定一个数量是无符号类型时,那么其最高位的1或0,和其它位一样,用来表 示该数的大小。 当我们指定一个数量是无符号类型时,此时,最高数称为“符号位”。为1时,表示该 数为负值,为0时表示为 3、无符号数和有符号数的范围区别。 无符号数中,所有的位都用于直接表示该值的大小。有符号数中最高位用于表示正负 所以,当为正值时,该数的最大值就会变小。我们举一个字节的数值对比 无符号数:1111值:2551*2+1*2°+1*2+1*2+1*2+1*2+ 有符号数:01111111值:127 +1*2+1* +1*2-+1*2+1
在计算机中,可以区分正负的类型,称为有符类型,无正负的类型(只有正值),称为 无符类型。 数值类型分为整型或实型,其中整型又分为无符类型或有符类型,而实型则只有符类型。 字符类型也分为有符和无符类型。 比如有两个量,年龄和库存,我们可以定前者为无符的字符类型,后者定为有符的整数 类型。 2、使用二制数中的最高位表示正负。 首先得知道最高位是哪一位?1 个字节的类型,如字符类型,最高位是第 7 位,2 个字 节的数,最高位是第 15 位,4 个字节的数,最高位是第 31 位。不同长度的数值类型,其最 高位也就不同,但总是最左边的那位(如下示意)。字符类型固定是 1 个字节,所以最高 位总是第 7 位。 (红色为最高位) 单字节数: 1111 1111 双字节数: 1111 1111 1111 1111 四字节数: 1111 1111 1111 1111 1111 1111 1111 1111 当我们指定一个数量是无符号类型时,那么其最高位的 1 或 0,和其它位一样,用来表 示该数的大小。 当我们指定一个数量是无符号类型时,此时,最高数称为“符号位”。为 1 时,表示该 数为负值,为 0 时表示为正值。 3、无符号数和有符号数的范围区别。 无符号数中,所有的位都用于直接表示该值的大小。有符号数中最高位用于表示正负, 所以,当为正值时,该数的最大值就会变小。我们举一个字节的数值对比: 无符号数: 1111 1111 值:255 1* 27 + 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20 有符号数: 0111 1111 值:127 1* 26 + 1* 25 + 1* 24 + 1* 23 + 1* 22 + 1* 21 + 1* 20
同样是一个字节,无符号数的最大值是255,而有符号数的最大值是127。原因是有符 号数中的最高位被挪去表示符号了。并且,我们知道,最高位的权值也是最高的(对于1 字节数来说是2的7次方=128),所以仅仅少于一位,最大值一下子减半 不过,有符号数的长处是它可以表示负数。因此,虽然它的在最大值缩水了,却在负值 的方向出现了伸展。我们仍一个字节的数值对比 无符号数 55 有符号数 128 0 同样是一个字节,无符号的最小值是0,而有符号数的最小值是-128。所以二者能表 达的不同的数值的个数都一样是256个。只不过前者表达的是0到255这256个数,后者 表达的是-128到+127这256个数 个有符号的数据类型的最小值是如何计算出来的呢? 有符号的数据类型的最大值的计算方法完全和无符号一样,只不过它少了一个最高位 (见第3点)。但在负值范围内,数值的计算方法不能直接使用1*2+1*253的公式进行 转换。在计算机中,负数除为最高位为1以外,还采用补码形式进行表达。所以在计算其 值前,需要对补码进行还原。这些内容我们将在第六章中的二进制知识中统一学习 这里,先直观地看一眼补码的形式 以我们原有的数学经验,在10进制中:1表示正1,而加上负号:-1表示和1相对的 负值。 那么,我们会很容易认为在2进制中(1个字节):00000001表示正1,则高位为1 后:10000001应该表示-1 然而,事实上计算机中的规定有些相反,请看下表 进制值(1字节) 十进制值 10000000 10000001 10000010 126 10000011 125
同样是一个字节,无符号数的最大值是 255,而有符号数的最大值是 127。原因是有符 号数中的最高位被挪去表示符号了。并且,我们知道,最高位的权值也是最高的(对于 1 字节数来说是 2 的 7 次方=128),所以仅仅少于一位,最大值一下子减半。 不过,有符号数的长处是它可以表示负数。因此,虽然它的在最大值缩水了,却在负值 的方向出现了伸展。我们仍一个字节的数值对比: 无符号数: 0 ----------------- 255 有符号数: -128 --------- 0 ---------- 127 同样是一个字节,无符号的最小值是 0 ,而有符号数的最小值是-128。所以二者能表 达的不同的数值的个数都一样是 256 个。只不过前者表达的是 0 到 255 这 256 个数,后者 表达的是-128 到+127 这 256 个数。 一个有符号的数据类型的最小值是如何计算出来的呢? 有符号的数据类型的最大值的计算方法完全和无符号一样,只不过它少了一个最高位 (见第 3 点)。但在负值范围内,数值的计算方法不能直接使用 1* 26 + 1* 25 的公式进行 转换。在计算机中,负数除为最高位为 1 以外,还采用补码形式进行表达。所以在计算其 值前,需要对补码进行还原。这些内容我们将在第六章中的二进制知识中统一学习。 这里,先直观地看一眼补码的形式: 以我们原有的数学经验,在 10 进制中:1 表示正 1,而加上负号:-1 表示和 1 相对的 负值。 那么,我们会很容易认为在 2 进制中(1 个字节): 0000 0001 表示正 1,则高位为 1 后:1000 0001 应该表示-1。 然而,事实上计算机中的规定有些相反,请看下表: 二进制值(1 字节) 十进制值 1000 0000 -128 1000 0001 -127 1000 0010 -126 1000 0011 -125 ...
ll111110 l1111111 首先我们看到,从-1到-128,其二进制的最高位都是1(表中标为红色),正如我们前 面的学。 然后我们有些奇怪地发现,10000000并没有拿来表示-0:而10000001也不是拿来 直观地表示-1。事实上,-1用11111111来表示 怎么理解这个问题呢?先得问一句是-1大还是-128大? 当然是-1大。-1是最大的负整数。以此对应,计算机中无论是字符类型,或者是整数 类型,也无论这个整数是几个字节。它都用全1来表示-1。比如一个字节的数值中:1111 1111表示-1,那么,111111-1是什么呢?和现实中的计算结果完全一致。11111 -1=111110,而111110就是-2。这样一直减下去,当减到只剩最高位用于表示符 号的1以外,其它低位全为0时,就是最小的负值了,在一字节中,最小的负值是1000000 也就是-128。 我们以-1为例,来看看不同字节数的整数中,如何表达-1这个数: 节数 进制值 十进制值 单字节数 11111111 双字节数 1111111111111111 四字节数 11111111111111111111111111111111 可能有同学这时会混了:为什么11111时表示255,有时又表示-1?所以我再强 调一下本节前面所说的第2点:你自已决定一个数是有符号还是无符号的。写程序时,指 定一个量是有符号的,那么当这个量的二进制各位上都是1时,它表示的数就是-1:相反, 如果事选声明这个量是无符号的,此时它表示的就是该量允许的最大值,对于一个字节的 数来说,最大值就是255 这一节课,看似罗嗦,但我希望每位没有编程基础,或者以前对进制,对负值、补码、 反码等概念,对数据类型理解不透彻的学员,都能多花时间反复阅读,直到看懂得文中的 每一张图表的意思为止。如果有困难,请发信到问答处的专门信箱:wenda@bcbschool.com (为了方便我的查阅,请无关课程的问答或其它来信,不要发到这个邮址,谢谢)
1111 1110 -2 1111 1111 -1 首先我们看到,从-1 到-128,其二进制的最高位都是 1(表中标为红色),正如我们前 面的学。 然后我们有些奇怪地发现,1000 0000 并没有拿来表示 -0;而 1000 0001 也不是拿来 直观地表示-1。事实上,-1 用 1111 1111 来表示。 怎么理解这个问题呢?先得问一句是-1 大还是-128 大? 当然是 -1 大。-1 是最大的负整数。以此对应,计算机中无论是字符类型,或者是整数 类型,也无论这个整数是几个字节。它都用全 1 来表示 -1。比如一个字节的数值中:1111 1111 表示-1,那么,1111 1111 - 1 是什么呢?和现实中的计算结果完全一致。1111 1111 - 1 = 1111 1110,而 1111 1110 就是-2。这样一直减下去,当减到只剩最高位用于表示符 号的 1 以外,其它低位全为 0 时,就是最小的负值了,在一字节中,最小的负值是 1000 0000, 也就是-128。 我们以-1 为例,来看看不同字节数的整数中,如何表达-1 这个数: 字节数 二进制值 十进制值 单字节数 1111 1111 -1 双字节数 1111 1111 1111 1111 -1 四字节数 1111 1111 1111 1111 1111 1111 1111 1111 -1 可能有同学这时会混了:为什么 1111 1111 有时表示 255,有时又表示-1?所以我再强 调一下本节前面所说的第 2 点:你自已决定一个数是有符号还是无符号的。写程序时,指 定一个量是有符号的,那么当这个量的二进制各位上都是 1 时,它表示的数就是-1;相反, 如果事选声明这个量是无符号的,此时它表示的就是该量允许的最大值,对于一个字节的 数来说,最大值就是 255。 这一节课,看似罗嗦,但我希望每位没有编程基础,或者以前对进制,对负值、补码、 反码等概念,对数据类型理解不透彻的学员,都能多花时间反复阅读,直到看懂得文中的 每一张图表的意思为止。如果有困难,请发信到问答处的专门信箱:wenda@bcbschool.com (为了方便我的查阅,请无关课程的问答或其它来信,不要发到这个邮址,谢谢)