位、字节、地址
- 位(bit):又称“比特”。每一个二极管元件称为一个“二进制位”,是存储信息的最小单位。它的值是1或0。
- 字节(byte):又称拜特。一般将8个“二级制位”组织成一组,称为“字节”。
- 地址:
不同类型数据的存储方式
整数
讲解整数的存储之前,首先要了解原码、反码和补码这几个概念。
- 原码:将一个整数,转换成二进制,就是其原码。例如单字节5的原码为0000 0101,-5的原码为1000 0101。
- 反码:正数的反码就是其原码;负数的反码是将原码中除符号位以外的每一位取反。例如单字节5的反码为 0000 0101,-5的反码为1111 1010。
- 补码:正数的补码就是其原码;负数的补码是其反码加1。例如单字节5的补码为 0000 0101,-5的原码为
1111 1011。
在计算机内存中,数值一律采用补码表示。使用补码可以将符号位和数值域统一处理,使用加法电路来计算减法,简化了硬件电路。
例如,16-9 = 16+(-9),16 的补码为 0001 0000,-9 的原码为 1000 1001,补码为 1111 0111。我们可以直接将两个数的补码相加:
1111 0111 + 0001 0000 = 1 0000 0111
最高位的1溢出,被截去,内存中最后剩下 0000 0111,也就是7。
实数
实数在计算机内按照标准化指数形式存储。
标准化指数形式:其数值部分是一个小数,小数点前的数字是零,小数点后的第一位数字不是零。
- %f是浮点数,输出f中保存的浮点数
- %10f表示输出浮点数f中的前10位
- %10.2f表示场宽为10,其中有2位小数
- %.2f表示输出2位小数
- %-10.2f同10.2f,但输出之后左对齐,而不是右对齐。
- 浮点数存储误差关键取决于浮点数存储的性质,它实际上是通过一组2的幂相加之和来存储一个数字,所以理论上是不会完全精准的。但不同编译器可能也有不同的解析,具体更细节的部分建议你参照一下相关编译器浮点数的存储结构。
字符
计算机将字符的代码(查ASCII表)存储到相应的存储单元中。
符号常量
比如 # define PI 3.1415926
#define 不是C语句,该行的末尾没有分号。它是一个“预编译命令”。也就是简单的字符置换,无论置换的字符是否有含义都进行置换。
符号常量只是一个符号,不占存储单元。
符号常量是不能被赋值的。
运算
整型数据运算
%d:用来输出十进制整数。
- C语言规定,两个整型数据相除结果是整型。
- C语言变量名的取名规则:第一个字符必须是字母或下划线,其后的字符必须是字母、数字或下划线。
- 在C语言中,把用来标识对象(包括变量、函数、数组、类型等)名字的有效字符系列称为标识符。以上命名规则适用于所有标识符。
- 大小写字母代表不同的字符
- 变量的长度不是无限的
- 整型变量可以进行求余运算,实数不行
C语言中可以定义和使用以下6中整型变量:
- 有符号基本整型 【signed】int
- 无符号基本整型 unsigned int
- 有符号短整型 【signed】 short 【int】
- 无符号短整型 unsigned short 【int】
- 有符号长整型 【signed】 long【int】
- 无符号长整型 unsigned long【int】
实数数据的运算
- %f:用来输出浮点数。
- C编译系统把所有float(实型)常量(如0.08)都作为双精度数据来处理。
- log10 函数的值是double(双精度型)。
- sizeof是C语言中的运算符,用来测定类型或变量的长度。用法是:sizeof(类型名)或sizeof(变量名)。
- 用数学函数时必须用math.h头文件
- 一般占4个字节的单精度数据的取值范围为10E-38~10E38,有效位数为7位。
- 双精度数据的取值范围为10E-308~10E308,有效位数为15~16位。
在IEEE754标准中进行了单精度浮点数(float)和双精度数浮点数(double)的定义。float有32bit,double有64bit。它们的构成包括符号位、指数位和尾数位。
这些位的构成如下:
- 种类——-符号位————-指数位—————-尾数位—-
- float——第31位(占1bit)—-第30-23位(占8bit)—-第22-0位(占23bit)
- double—第63位(占1bit)—-第62-52位(占11bit)—第51-0位(占52bit)
单精度实型变量和双精度实型变量的根本区别在于所存储数据的内存空间大小不同。
取值范围主要看指数部分:
- float的指数部分有8bit(2^8),由于是有符号型,所以得到对应的指数范围-126~127。
- double的指数部分有11bit(2^11),由于是有符号型,所以得到对应的指数范围-1023~1022。
由于float的指数部分对应的指数范围为-126~127,所以取值范围为:
- -2^-126到2^127,约等于-3.4E38 — +3.4E38
精度(有效数字)主要看尾数位:
- float的尾数位是23bit,2^23=8388608 , 这样单精度浮点数能表示的有效数据只能是6-7位,即:7位以上的数据,无法在单精度中进行精确存储了,只能丢弃部分数据。
- double的尾数位是52bit,2^52=4503599627370496, 这样双精度浮点数能表示的有效数据只能是15-16位,即:16位以上的数据,无法在双精度中进行精确存储了,只能丢弃部分数据。
转换大致过程如下:
将十进制数转为二进制数 用类似于科学计数法的形式表示成
V=(-1)^s*(1+M)*2^(E-127)(单精度)
V=(-1)^s*(1+M)*2^(E-1023)(双精度)
然后将每部分算出的数值按顺序排列
例如:
-0.0625=-1.0*2^(-4)
s=1,M=1-1=0,E=-4 +127=123=0111 1011 ,
E(双精度)=-4 +1023=1019 =0111 1111 011
单精度:1011 1101 1000 0000 0000 0000 0000 0000
双精度:1011 1111 1011 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
以0.421875为例,转换为二进制 0.421875 = 0.011011 = 1.1011e(-2)
e = -2,数码s=0,E = -2+127(01111111) = 125 尾数M=1011
因此存储格式为:
0 01111101 1011 000 0000 0000 0000 0000
什么是IEEE754标准
用来规范化浮点数,其格式是
(1)32位
x=(-1)s×(1.M)×2E-127 e=E-127
(2)64位
x=(-1)s×(1.M)×2E-1023 e=E-1023
其中,s是符号位,M是尾数,E是阶码,e是实际的指数值
- | - | - | - |
---|---|---|---|
参数 | 单精度浮点数 | 双精度浮点数 | 扩充精度浮点数 |
浮点数字长 | 32 | 64 | 80 |
尾数长度P | 23 | 52 | 64 |
符号位S | 1 | 1 | 1 |
指数长度E | 8 | 11 | 15 |
最大指数 | +127 | +1023 | +16383 |
最小指数 | -126 | -1022 | -16382 |
指数偏移量 | +127 | +1023 | +16383 |
可表示的实数范围 | 10^-38~10^38 | 10^-308~10^308 | 10^-4932~10^4932 |
为什么阶码的偏移量是127?
对于阶码为0或为255(2047)的情况,IEEE有特殊的规定:
如果 E 是0 并且 M 是0,表示的真值x 为零,结合符号位S 为0或1,有正零和负零之分。
如果 E = 255 并且 M 是0,表示的真值x 为无穷大,结合符号位S 为0或1,也有+∞和-∞之分。
如果 E = 255 并且 M 非0,这个数表示为不是一个数(NaN)。
再来看看下什么机器零:
- (1)当浮点数尾数M=0,无论阶码E为何值,则该浮点数为0值
- (2)当阶码的值遇到比它所能表示的最小值还小时,不管尾数M为何值,则浮点数为0值
(1)、(2)中的零值称为机器零
“考虑到在32位浮点数表示中,要除去E 用全0和全1(255)10表示零和无穷大的特殊情况,指数的偏移值不选128(10000000),而选127(01111111)。对于规格化浮点数,E 的范围变为1到254,真正的指数值e 则为-126到+127。因此32位浮点数表示的绝对值的范围是10-38~1038(以10的幂表示)。”——引自 白中英<<计算机组成原理>>
- | - | - | - |
---|---|---|---|
S(1位) | E(8位) | M(23位) | N(32位) |
符 | 0 | 0 | (-1)S *2E-127·(1.M) 为规格化数 |
0 | 不等于0 | (-1)S*2-126*(0.M) 为非规格化数 | |
号 | 1到254之间 | 不等于0 | (-1)S*2E-127*(1.M) 为规格化数 |
255 | 不等于0 | NaN(非数值) | |
位 | 255 | 0 | 无穷大 |
其中红色字0、1表示隐含位,注意当数字N为非规格化数或是0时,隐含位是0。
- 如果选择偏移值128时,假设指数(不是阶码)为+127,按照e=E-128,则阶码为127+128=255,全为1,由上表可知N为NaN和无穷大
- 假设指数为0(包括正0和负0),按e=E-128,则正0+128=128,负0(补码)+128=0,由上可知E=0时,存在非规格化数
- 由于8位E中,只有7位有效数字,7位能表示的大小为0-127,所以偏移量可以在0-127中任取一值,在IEEE754Z中规定取127.
为什么阶码表示的最小指数是-126呢?
有2中描述可以得到,当偏移量为127时,若最小指数是-127,按e=E-127,则127+(-127)=0,E=0,存在非规格化数
故取-126,这也符合E的表示范围1~254。
字符型数据运算
转义字符 | 含义 |
---|---|
\t | 使下一个输出的数据跳到下一个输出区(一行中一个输出区占7列) |
\b | 退格 |
\r | 回车,将当前的输出位置返回在本行开头 |
\f | 换页。将当前的输出位置移到下页的开头 |
\0 | 代表ASCII代码为0的控制字符,即“空操作”的字符。常用语字符串中,作为字符串的结束标志 |
\ddd | 1~3位八进制数所代表的字符, ddd对应 1~3位八进制数,\101 ,101是8进制数,转换为10进制是65,那么\101 对应的字符就是数字65对应的字符(请参考assic表),就是A。同理 \102 对应的字符就是B. |
\xhh | 1~2位十六进制数所代表的字符,hh 对应 1-2位16进制数。 |
字符数据和整型数据的存储从形式上没有什么区别,这样就使字符型数据和整型数据之间可以通用。可以将一个整数赋给一个字符变量,如下面两行语句等价:
char c = 'a';
char c = 97;
要注意的是,赋给字符变量的整数范围为0~127,它们对应有效的字符。
字符数据既可以以字符形式(用%c格式)输出,也可以以整数形式(用%d格式)输出。
字符数据与整型数据的区别:
字符数据只占1个字节,而在Visual
C++中整型数据占4个字节,显然不能把一个大数(如12345)存到字符变量中。因此绝不能用字符变量代替整型变量去使用。
字符串常量
‘a’和“a”有什么区别?
C语言编译系统在处理字符串时,在每一个字符串常量结尾加一个字符“\0”,作为字符串结束的标志。“a”实际上包含2个字符:‘a’和‘\0’。
在C语言中没有专门的字符串常量,不能将一个字符串存放在一个变量中。如果想将一个字符串存放在内存中,必须使用字符数组。
算术运算符和算术表达式
- ++i,- -i 在使用i之前,先使i的值+/-1
- i++,i- - 在使用i之后,使i的值+/-1
- 自增运算发(++)和自减运算符(–)只能用于变量,而不能用于常量或表达式,如5++或(a+b)++都是不合法的。
- a = 4,b = 5;a+++b=(a++)+b = 9;
- C语言允许整型(包括int,short,long)和实型数据(包括float,double,long double)进行混合运算。由于字符型数据可以与整型通用,因此,整型、实型、字符型数据间可以混合运算。在进行运算时,不同类型的数据要先转换成同一类型,然后进行运算。转换的规则为:
- char和short型转换为int型。
- float型一律转换为double型。
- 整型(包括int,short,long)数据与double型数据进行运算,先将整型转换为double型。
- 在强制类型转换时,得到一个所需类型的中间变量,原来变量的类型未发生变化。
- “%”运算符要求其两侧均为整型量,若x为float,则“x%3”不合法,必须用“(int)x%3”。强制类型转换运算优先于%运算。
- a = -5++;是(-5)++还是-(5++)呢?-和++的优先级相同,按右结合性应该是后者,a = -6。
输出格式符
%d:输入输出为整形 %ld 长整型 %hd短整型
%c用来输出一个字符,
%s用来输出一个字符串
%f:输入输出为浮点型 %lf双精度浮点型
%o以八进制数形式输出整数
%x以十六进制数形式输出整数
%e以指数形式输出实数
%g根据大小自动选f格式或e格式,且不输出无意义的零。
%u以十进制数输出unsigned型数据(无符号数)。
%hu代表以 unsigned short格式输出整数
%hx 代表以16进制的 输出short类型的整数 搜索
比如
printf(“%hu\n”,-30); 会输出 65506
printf(“%hx\n”,-30); 会输出FFE2
C语言格式输出函数printf()详解_C语言中文网
http://c.biancheng.net/cpp/html/33.html
,
习题
引用:
学习IEEE754标准需要注意的几个问题 - hongdi也IT - 博客频道 - CSDN.NET
32位浮点数表示的范围_百度文库
IEEE754标准的32位浮点数-Frank的博客
实型变量单精度(float)的范围是怎么算出来的-3.4×10(38)~3.4×10(38)_百度知道
IEEE 754标准如何转换?_百度知道
C语言中,单精度实型变量和双精度实型变量的具体区别是什么呀_百度知道
IEEE754标准(浮点数格式标准)-日志分享
【图文】教学内容: 31 数据类型 32 整型数据 33 实型数据 34 字符_百度文库