网站接入商,怎么做网站视频,佛山网站设计实力乐云seo,搜索引擎网站【第19节 C语言语法进阶】
【19.1 条件运算符与逗号运算符】
1 条件运算符
条件运算符是C语言中唯一的一种三亩运算符。三目运算符代表有三个操作数#xff1b;双目运算符代表有两个操作数#xff0c;如逻辑运算符就是双目运算符#xff1b;弹幕运算符代表有一个操作数双目运算符代表有两个操作数如逻辑运算符就是双目运算符弹幕运算符代表有一个操作数如逻辑非就是单目运算符。运算符也称操作符。三目运算符通过判断问号之前的表示的真假来确定整体表达式的值如下例所示如果ab为真那么三目表达式整体的值为a所以max的值等于a如果ab为假那么三目表达式整体的值为b所以max的值等于b。
#include stdio.hint main(){int a,b,max;while(scanf(%d%d,a,b)){max a b ? a : b;printf(max %d\n,max);}return 0;
} 2 逗号运算符
逗号运算符的优先级最低逗号表达式的整体值是最后一个表达式的值。
#include stdio.h
int main(){int i,j;i 10;j 1;if(i,--j){ // 不会进入if逗号表达式整体的值是最后一个表达式的值 j是-1printf(condition value is:j %d,if excute\n,j);}if(i,j){ // 进入if逗号表达式整体的值是最后一个表达式的值 j是0printf(condition value is:j %d,if excute\n,j);}for (i 0,j 1; i 10; i) { // 逗号表达式的常见场景for的表达式1初始化多个变量用的较多}return 0;
} 【19.1 题】
1、条件运算符是C语言唯一的三目运算符优先级高于赋值运算符。
2、maxab?a:b;通过这种方式max可以获取a和b中较大的那个数。
3、逗号运算符的优先级低于赋值运算符逗号表达式的整体值是最后一个表达式的值。
【19.2 自增自减运算符】
1 自增自减运算符
自增、自减运算符和其他运算符有很大区别因为其他运算符除赋值运算可以改变变量本身的值外不会有这种效果。自增、自减就是对变量自身进行加1、减1操作那么有了加法和减法运算符为啥还要发明这种运算符呢原因是自增自减来源于B语言当时ken thompson和dennis M.ritchieC语言的发明者为了不改变程序员的编写习惯在C语言中保留了B语言的自增和自减。因为自增、自减会改变变量的值所以自增和自减不能用于常量。
下例中的ji-1对于后或者后--需要去掉或--运算符也就是首先计算jj-1因为i本身等于-1所以得到j的值为0接着单独计算i也就是对i加1所以i从-1加1得到0因此printf(i%d,j%d,i,j);语句的执行结果是0和0。
#include stdio.h
int main(){int i,j;i -1;
// 5; // 编译不通自增自减不能用于常量j i 1; // j i 1;i;printf(i %d,j %d,i,j); // i 0,j 0return 0;
} 2 自增自减运算符与取值运算符
只有比后增优先级高的操作才会走位一个整体如()、[]
#include stdio.h
int main(){int a[3] {2,7,8};int *p;int j;p a;j *p; // 先把*p的值赋给j然后对p加1j a[0],p a[1]printf(a[0] %d,j %d,*p %d\n,a[0],j,*p); // 227j p[0]; // 先把p[0]的值赋给j然后对p[0]加1,j a[1],p a[2]printf(a[0] %d,j %d,*p %d\n,a[0],j,*p); // 278return 0;
} 【19.2 题】
1、a10执行ba后a的值是11b的值是10。
2、a10执行ba--后a的值是9b的值是10.
3、int a[3] {2,7,8};int *p a;执行了j *p;后p指向元素a[1].整型指针变量加1偏移4个字节因此指向a[1]。
【19.3 位运算符】
1 位运算符
位运算符、、、|、^、依次是左移、右移、按位取反、按位或、按位异或、按位与。
位运算符只能用于对整型数据进行操作。
左移高位丢弃低位补0相当于乘以2一半申请内存时会用左移例如要申请1GB大小的空间可以使用malloc(130)。
右移低位丢弃整数的高位补0无符号数认为是正数负数的高位补1相当于除以2移位比乘法和除法的效率要高负数右移对偶数来说是除以2但对奇数来说是先减1后除以2。例如-81得到的是-4但-71得到的并不是-3而是-4。另外对于-1来说无论右移多少位值永远为-1.
C语言的左移和右移相当于是算数左移与算数右移。考研中的逻辑左移与右移左移和右移空位都补0.
异或相同的数进行异或时结果为0任何数和0异或的结果是其本身。
按位取反数位上的数是1变为00变为1.
按位与和按位或用两个数的每一位进行与和或。
// bit operator
#include stdio.h
int main(){short i 5;short j;j i 1; // j i*2 10,i 5printf(j %d\n,j); // j 10j i 1; // j i/2 2,i 5printf(j %d\n,j); // j 2i 0x8011; // 1000 0000 0001 0001unsigned short s 0x8011; // 1000 0000 0001 0001unsigned short r 0;j i 1; // i 1 11000 0000 0001 000 1100 0000 0000 1000 A008r s 1; // s 1 01000 0000 0001 000 0100 0000 0000 1000 4008printf(j %d,r %d\n,j,r);i 5,j 7; // 5 0000 01017 0000 0111printf(i j %d\n,i j); // 0000 0101 5printf(i | j %d\n,i | j); // 0000 0111 7printf(i ^ j %d\n,i ^ j); // 0000 0010 2printf(~i %d\n,~i); // 按位取反的结果是负数该负数是原数的补码需要将补码转换成原数原数是按位取反加1再加上负号。return 0;
} 2 异或运算符示例解析
异或运算符有两个特性一是任何数和零异或得到的是自身两个相等的数异或得到的是零通过这两个特性可以在一堆数中找出出现1次的那个数其他数是出现2次。异或满足交换律。
#include stdio.h// XOR Exclusive OR
int main(){int arr[5] {8,5,3,5,8};int result 0; // 任何数和0异或都是自身for (int i 0; i 5; i) {result ^ arr[i]; // 两个相等的数异或得到的是零异或满足交换律}printf(result %d\n,result);return 0;
} 【19.3 题】
1、57得到的值是5. // 0000 0101 0000 0111 0000 0101 5
2、51得到的值是10-71得到的值是-4. // 5左移1位5*210-7右移1位-7-1/2-4
3、5^5得到的值是07^0得到的值是7. // 数和本身异或结果都为0相同的数异或结果为0数和0异或结果都为数本身。
【19.4 switch do-while】
1 switch选择语句讲解
判断一个变量可以等于几个值或几十个值时使用if和else if语句会导致else if分支非常多这时可以考虑使用switch语句switch语句的语法格式如下
switch(表达式)
{case 常量表达式1:语句1case 常量表达式2:语句2...case 常量表达式n:语句ndefault:语句n1
}使用switch语句的例子。输入一个年份和月份然后打印队医你给月份的天数如输入一个闰年和2月则输出为29天。具体代码如下所示switch语句中case后面的常量表达式的值不是按照1到12的顺序排列的。switch语句匹配并不需要常量表达式的值有序排列输入值等于哪个常量表达式的值就执行其后的语句每条语句后面需要加上break语句代表匹配成功一个常量表达式时就不再匹配并跳出switch语句。
【例1】switch语句的使用。
#include stdio.h// switch
int main(){int year,month;while(scanf(%d%d,year,month)){switch (month) {case 1:printf(year %d,month %d,have 31 days\n,year,month);break;case 2:printf(year %d,month %d,have %d days\n,year,month,28(year%4000 || year%100!0 year%40));break;case 3:printf(year %d,month %d,have 31 days\n,year,month);break;case 4:printf(year %d,month %d,have 30 days\n,year,month);break;case 5:printf(year %d,month %d,have 31 days\n,year,month);break;case 6:printf(year %d,month %d,have 30 days\n,year,month);break;case 7:printf(year %d,month %d,have 31 days\n,year,month);break;case 8:printf(year %d,month %d,have 31 days\n,year,month);break;case 9:printf(year %d,month %d,have 30 days\n,year,month);break;case 10:printf(year %d,month %d,have 31 days\n,year,month);break;case 11:printf(year %d,month %d,have 30 days\n,year,month);break;case 12:printf(year %d,month %d,have 31 days\n,year,month);break;default:printf(invalid month\n);}}return 0;
}
如果一个case语句后面没有break语句那么程序会继续匹配下面的case常量表达式。代码优化。原理是只要匹配到1、3、5、7、8、10、12中的任何一个就不再拿month与case后的常量表达式的值进行比较而执行语句printf完毕后执行break语句跳出switch语句switch语句最后加入default的目的是在所有case后的常量表达式的值都未匹配时打印输出错误标志或着一些提醒。
【例2】日期示例改进。
#include stdio.h// switch
int main(){int year,month;while(scanf(%d%d,year,month)){switch (month) {case 1:case 3:case 5:case 7:case 8:case 10:case 12:printf(year %d,month %d,have 31 days\n,year,month);break;case 4:case 6:case 9:case 11:printf(year %d,month %d,have 30 days\n,year,month);break;case 2:printf(year %d,month %d,have %d days\n,year,month,28(year%4000 || year%100!0 year%40));break;default:printf(invalid month\n);}}return 0;
} 2 do while循环讲解
do while语句的特点是先执行循环体后判断循环条件是否成立。其一般形式为
do{循环体语句
}while(表达式);
执行过程如下首先执行一次指定的循环语句然后判断表达式当表达式的值为非零真时返回重新执行循环体语句如此反复直到表达式的值等于0为止。例3是使用do while语句计算1到100之间所有整数之和的例子do while语句与while语句的差别是do while语句第一次执行循环体内语句之前不会判断表达式的值也就是如果i的初值为101那么依然会进入循环体。实际情况中do while语句应用较少。
【例3】do while语句计算1到100之间的所有整数之和
#include stdio.h// do while
int main(){int i 0,sum0;do{sum i;} while (i 100);printf(%d\n,sum);i 0,sum0;do{sum sum i;i;} while (i 100);printf(%d\n,sum);i 101,sum0;do{sum sum i;i;} while (i 100); // 循环体总是会先执行一次printf(%d\n,sum);return 0;
} 【19.4 题】
1、switch的case后只能放常量表达式。常量表达式的值是整型、字符因为字符也可以是一个整型值。
2、case后如果没有break那么不会匹配后面的case的表达式直接执行表达式后的语句。
3、do while循环如果while()括号内的表达式为假第一次仍然会进入循环。
【19.5 二维数组、二级指针】
1 二维数组讲解
二维数组定义的一般形式如下
类型说明符 数组名[常量表达式][常量表达式];
例如定义a为3*4(3行4列)的数组b为5*10(5行10列)的数组
float a[3][4],b[5][10];
可以将二位数组视为一种特殊的一维数组一个数组中的元素类型是一维数组的一维数组。
例如可以把二维数组a[3][4]视为一个一维数组他有3个元素a[0] a[1] a[2]每个元素又是一个包含4个元素的一维数组如图1所示。
二维数组中的元素在内存中的存储规则是按行存储即先顺序存储在第一行的元素后顺序存储第二行的元素数组元素的获取依次是从a[0][0]到a[0][1]直到最后一个元素a[2][3]。
图2中显示了存储二维数组a[3][4]中每个元素时的顺序。 #include stdio.h// Two-dimensional array
int main(){int arr[3][4] {1,2,3,4,5,6,7,8,9};printf(sizeof(arr) %d\n,sizeof (arr)); // 3*4*sizeof(int) 3*4*4printf(arr[2][3] %d\n,arr[2][3]); // 二维数组的最后一个元素return 0;
} 2 二级指针讲解
二级指针是指针的指针二级指针的作用是服务于一级指针变量对一级指针变量实现间接访问。
#include stdio.h// Two-level pointer
int main(){int i 10;int *p i; // p指向i的地址int **q p; // q指向p的地址 如果需要把一个一级指针变量的地址存起来就需要二级指针类型printf(sizeof(i) %d,i %d,i %d\n,sizeof (i),i,i);printf(sizeof(p) %d,p %d,*p %d\n,sizeof (p),p,*p);printf(sizeof(q) %d,q %d,*q %d,**q %d\n,sizeof (q),q,*q,**q); // 通过2次取值可以拿到i的值return 0;
} 假设如下是内存 【19.5 题】
1、二维数组中的元素在内存中的存储规则是按行存储即先顺序存储第一行的元素后顺序存储第二行的元素直到最后一行。
2、定义int a[3][4];那么可以访问数组的最后一个元素是a[2][3]。
3、二级指针是存储一级指针变量的地址值也是用于做间接访问。
【19 代码题】
1、读取一个有符号数对其进行左移输出结果对其进行右移输出结果。例如输入数值5左移得到的结果是10右移得到的结果是2.不考虑左移后正值变为负值负值变为正值的情况每个输出占用2个字符位置采用%2d。
#include stdio.h// Two-dimensional array
int main(){int a;scanf(%d,a);int i a 1;int j a 1;printf(%2d\n,i);printf(%2d\n,j);return 0;
} 2、输入5个数其中2个数出现2次1个数是出现1次找出出现1次的那个数例如输入的是8 5 3 5 8输出的值为3.
#include stdio.h// XOR Exclusive OR
int main(){int num,result 0;for (int i 0; i 5; i) {scanf(%d,num);result result ^ num;}printf(%d\n,result);return 0;
} 【第20节 数据的机器级表示】
【20.2 与408关联】
2012年
13.假定编译器规定int和short型长度分别为32位和16位执行下列C语言语句
unsigned short x 65530;
unsigned int y x;
得到y的机器数为。
14.float 类型即IEEE754单精度浮点数格式能表示的最大整数是。
2013年
14.某字长为8位的计算机中已知整型变量x、y的机器数分别为[x]补1 1110100,[y]补10110000.若整型变量z2*xy/2则z的机器数为。
2016年
13.有如下C语言程序段
short si -32767;
unsigned short usi si;
执行上述两条语句后usi的值为。
14.某计算机字长为32位按字节编址采用小端Little Endian方式存放数据。假定有一个double型变量其机器表示位1122 3344 5566 7788H存放在0000 8040H开始的连续存储单元中则存储单元0000 8046中存放的是。
2018年
13.假定带符号整数采用补码表示若int型变量x和y的机器数分别是FFFF FFDFH和0000 0041H则xy的值以及x-y的机器数分别是。
14.IEEE754单精度浮点格式表示的数中最小的规格化正数是。
15.某32位计算机按字节编址采用小端Little Endian方式若语令int i 0;对应指令的机器代码为C7 45 FC 00 00 00 00则语句int i -64;对应指令的机器代码是。
16.整数x的机器数为1101 1000分别对x进行逻辑右移1位和算数右移1位操作得到的机器数各是。
2019年
13.考虑一下C语言代码
unsigned short usi 65535;
short si usi;
执行上述程序段后si的值是。
2 本节内容介绍
本大节课分为20.3小节到20.7小节包含补码解析整型不同类型、溢出解析浮点数IEEE754标准解析真题实战
20.3小节是补码讲解及内存实战演示
20.4小节是整型不同类型解析-溢出解析
20.5小节是浮点数IEEE754标准解析及实战计算演示
20.6小节是浮点数精度丢失实战演示
20.7小节是选择题真题讲解
【20.3 补码讲解及内存实战演示】
计算机的CPU无法做减法操作硬件上没有减法器只能做加法操作。CPU中有一个逻辑单元叫加法器。计算机所做的减法都是通过加法器将其变化为加法实现的。实现2-5的方法是2-5。由于计算机只能存储0和1因此编写程序来查看计算机如何存储-55的二进制数为101称为原码。计算机用补码表示-5补码是对原码取反后加1的结果即计算机表示-5时会对5的二进制数101取反后加1如图1所示。-5在内存中存储为0xffff fffb因为5取反后得0xffff fffa加1后得0xffff fffb由于是X86架构是小端存储小端存储是低字节在前即低字节在低地址高字节在后即高字节在高地址fb对于0xffff fffb是最低的字节因此fb在最前面大端和小端相反对其加2后得0xffff fffd见图2他就是k的值。当最高位为1代表负数时要得到原码才能知道0xffff fffd的值即对其取反后加1也可以减1后取反结果是一样的得到3所以其值为-3.
求-5的补码原码50000 0000 0000 0000 0000 0000 0000 0101
取反1111 1111 1111 1111 1111 1111 1111 1010 ffff fffa
加1:1111 1111 1111 1111 1111 1111 1111 1011 ffff fffb
-5的补码是ffff fffb。电脑是X86架构X86架构是小端存储。电脑内存显示方式为小端存储即低字节在前高字节在后。-5的补码内存视图显示为fb ff ff ff
对负数加2即对负数的补码加2得0xffff fffd。原码为减1后取反或取反后加1
-5的补码加21111 1111 1111 1111 1111 1111 1111 1101 0xffff fffd内存视图显示为fd ff ff ff
-5的补码加2后取反1000 0000 0000 0000 0000 0000 0000 0010
-5的补码加2后取反加1:1000 0000 0000 0000 0000 0000 0000 0011-52的原码 #include stdio.h// complement
int main(){int i -5;int j -5 2;printf(%d\n,j);return 0;
} 考研注意假设变量A的值为-5通过8位表示那么A[补]值为1111 1011,A[原]的值为1000 0101符号位是不动的只有值的部分是5通过符号位不动其他值取反加1。正数的补码和原码一致。
反码是一种在计算机中数的机器码表示。对于单个数值二进制的0和1而言对其进行取反操作就是将0变为11变为0.正数的反码和原码一致负数的反码就是在原码的基础上符号保持不变其他位取反。 6是正数补码与原码一致-3的补码是1111 1101.
-3的原码0000 0011取反1111 1100加11111 1101.(补码)。原码先减1:1111 1100后取反1000 0011负数的原码为-3.考研的原码记住负数的符号位要保留。
【20.3 题】
1、负数是以补码形式在内存中进行存储的。
2、小端是低位在低地址高位在高地址小端低位在前高位在后而大端刚好相反低位在高地址高位在低地址大端低位在后高位在前。
3、对于int a -6;小端存储那么a在内存中从低地址到高地址的存储的效果是fa ff ff ff.
原码0000 0110.取反1111 1001.加1:1111 1010. fa
4、假设有2个8位的补码数A和BA[补]表示为1101 1010B[补]表示为0011 0101那么A[原]为1010 0110B[原]为0011 0101
A:1101 1010 - 1101 1001 - 0010 0110 -考研初试负数的符号位不变-1010 0110
B:0011 0101 - 0011 0101
【20.4 整型不同类型解析-溢出解析】
1 整型不同类型解析
整型变量包括6种类型。其中有符号短整型与无符号短整型的最高位所代表的意义不同。不同整型变量表示的整型数的范围如表超出范围会发生溢出现象导致计算出错。
有符号基本整型 (signed)int
有符号短整型 (signed)short
有符号长整型 (signed)long
无符号基本整型 (unsigned)int
无符号短整型 (unsigned)short
无符号短整型 (unsigned)short
有符号短整型short2个字节16位的最大值为2^15-1 32767
无符号短整型short2个字节16位的最大值位2^16-1 65535 短整型最小数是-32768-2^15.补码1000 0000原码1000 0000
考研补充说明
考研会考8位的也就是1个字节的整型数的大小对于1个字节的有符号类型的数值范围是-2^7~(2^7-1)也就是-128到127对于8位的无符号unsigned类型的数值范围是0(2^8-1)也就是0-255.
2 溢出解析
如下例有符号短整型数可以表示的最大值位32767当对其加1时b的值会变为多少实际运行打印得到的是-32768。因为32767对应的十六进制数为0x7fff加1后变为0x8000其首位为1因此变成了一个负数。取这个负数的原码后就是其本身值为32768所以0x8000是最小的负数即-32768。这时就发生了溢出对32767加1希望得到的值是32768但结果却是-32768因此导致计算结果错误。在使用整型变量时一定要注意数值的大小数值不能超过对应整型数的表示范围。在编写的程序中数值大于2^64-1时可以自行实现大整数加法。
2^15 32768
2^16 65536
2^31 2147483648
2^32 4294967296
#include stdio.h// overflow
int main(){int i;short a 32767;short b;long c; // 32位的程序是4个字节64位的是8个字节b a 1; // 发生了溢出解决溢出的办法是用更大的空间来存i a 1; // 用更大的空间来存printf(short b a(32767) 1 %d\n,b); // short b -32768printf(int i a(32767) 1 %d\n,i); // int i 32768i 2147483647;c i 1;printf(int i %d\n,i);printf(long c i(2147483647) 1 %d\n,c);printf(sizeof(long) %d\n,sizeof (long));// 无符号数unsigned int m 3;unsigned short n 0x8056; // 无符号类型最高位不认为是符号位 原码补码1000 0000 0101 0110unsigned long k 5;b 0x8056; // 有符号短整型 1000 0000 0101 0110 (负数的补码 原码0111 1111 1010 1010 考研保留符号位 1111 1111 1010 1010printf(b %d\n,b); // b是有符号类型所以输出是负值printf(n %u\n,n); // 无符号类型要用%u用%d是不规范的return 0;
} 【20.4 题】
1、一个C语言程序在一台32位机器上运行程序中定义了三个变量xyz其中x和z为int型y为short型。当x127y-9时执行赋值语句zxy后x、y和z的值分别时x0000 007FHyFFF7H,z0000 0076H.
int为32位short位16位又C语言的数据在内存中为补码形式故x、y的机器数写为0000 007FHFFF7H执行zxy时由于x是int型y是short型需将y的类型强制转换为int在机器中通过符号位扩展实现由于y的符号位为1故在y的前面添加16个1即可将y强制转换为int型其十六进制形式为FFFF FFF7H然后执行加法即0000 007FH FFFF FFF7H 0000 0076H其中最高位的进位1自然丢弃因此答案是x0000 007FH,yFFF7H,z00000 0076H.
y(原9) 0000 1001
y(补-9) 1111 0111
y 1111 1111 1111 1111 1111 1111 1111 0111
x 0000 0000 0000 0000 0000 0000 0111 1111
xy0000 0000 0000 0000 0000 0000 0111 0110 ...76H
2、假定有4个整数用8位补码分别表示r1FEHr2F2Hr390Hr4F8H若将运算结果存放在一个8位寄存器中则下列4个运算均不会发生溢出r1*r2(28). r2*r3(1568127,溢出). r1*r4(16). r2*r4(112).
用补码表示时8位寄存器所能表示的整数范围为-128-127由于r1-2,r2-14,r3-112,r4-8因此r2*r31568大于127因此结果溢出。
3、由3个“1”和5个“0”组成的8位二进制补码能表示的最小整数是-125.补码整数表示时负数的符号位为1数值位按位取反末位加1因此剩下的2个“1”在最低位时表示的是最小整数位1000 0011转换成真值为-125. 取反0111 1100-》加10111 1101 -》考研保留符号位1 111 1101 - 2^7-1-2 -125
【20.5 浮点数IEEE754标准解析及实战计算演示】
在C语言中要使用float关键字或double关键字定义浮点型变量。float型变量占用的内存空间为4字节double型变量占用的内存空间为8字节。与整型数据的存储方式不同浮点型数据是按照指数形式存储的。系统把一个浮点型数据分成小数部分用M表示和指数部分用E表示并分别存放指数部分采用规范化的指数形式指数也分正、负符号位用S表示如图1所示。 数符即符号位占1位是0时代表整数是1时代表负数表1是IEEE-754浮点型变量存储标准。 S是符号位用来表示正、负是1时代表负数是0时代表正数。
EE代表指数部分指数部分的值规定只能是1到254不能是全0全1指数部分运算前都要减去127这是IEEE-754的规定因为还要表示负指数这里的1000 0001转换为十进制数为129129-1272即实际指数部分为2.
MM代表小数部分这里0010 0000 0000 0000 000。底数左边省略存储了一个1这是IEEE-754的规定使用的实际底数表示为1.0010 0000 0000 0000 000。
上表1可以变为如下表格 #include stdio.hint main(){float f 4.5;float f1 1.456;printf(%f,%f1\n,f,f1);return 0;
}// 4090 0000 0100 0000 1001 0000 0000 0000 0000 0000 0 100 0000 1 001 0000 0000 0000 0000 0000
// 100 0000 1 2^7 1 129
// 129-127 2-》指数 2*24
// 001 0000 0000 0000 0000 0000
// 底数左边省略了1 1.001 0000 0000 0000 0000 0000
// 指数2-》右移2位乘以2*2 100.1 0000 0000 0000 0000 0000
// 转换成十进制4.5 2^21*2^(-1) 4.5// 3f ba 5e 35 0011 1111 1011 1010 0101 1110 0011 0101 0 011 1111 1 011 1010 0101 1110 0011 0101
// 011 1111 1 2^7-1 128 - 1 127
// 127 - 127 0-指数 2*01
// 底数左边省略了1 1.011 1010 0101 1110 0011 0101
// 转换成十进制2^0 2^-2 2^-3 2 ^-4 2^-6 10.250.166 1.41
上图中可以看到4.5也就是变量f的内存是00 00 90 40因为是小端钝出所以实际值是0x40900000.
先看f的小数部分如下表所示M灰色代表小数部分为0010 0000 0000 0000 0000 000总计23位底数左边省略存储了一个1这是IEEE-754的规定使用的实际底数表示为1.001000000.
指数部分计算机并不能直接计算10的幂次f的指数部分是表2的EEEEEEEE所对应的部分也就是1000 0001其十进制值为129129-1272即实际指数部分为2指数值为2代表2的2次幂因此将1.001向左移动2位即可也就是100.1然后转换为十进制数整数部分是4小数部分是2^-1刚好等于0.5因此十进制数位4.5.浮点数的小数部分是通过2^-12^-22^-3...来近似一个浮点数的。
小数部分乘以指数部分等价于左移2位对于小数部分1.001其十进制值为1.125那么1.125*指数部分也就是4就是1.125*44.5。 1.456也是就会死变量f1的内存是35 5e ba 3f因为是小端存储所以实际值是0x3fba5e35。
先看f1的小数部分M灰色代表小数部分这里为011 1010 0101总计23位底数左边省略了一个1这是IEEE-754的规定使用的实际底数表示为1.011 1010 0101 1110 0011 0101.
接着看指数部分计算机并不能直接计算10的幂次f1的指数部分是表3的EEEE EEEE所对应的部分也就是0111 1111其十进制值为127127-1270即实际指数部分为0指数值为0代表2的0次幂因此1.011 1010 0101 1110 0011 0101无需做移动。浮点数的戏哦啊数部分是通过2^02^-22^-32^-42^-6...来近似一个浮点数的。10.250.1250.06250.0156251.453125. 【20.6 浮点数精度丢失实战演示】
浮点型变量分为单精度float型、双精度double型。如表1所示因为浮点数使用的是指数表示法需要记忆数值的范围。
double有11位指数52位小数。 上表中double类型是-1022到1023是通过1-2046因为不能是全0全1全1是2047减去1023得到-1022到1023.
如下例所示赋给a的值为1.23456789e10加20后应该得到的值为1.234567892e10但b输出结果却是b12345678.000000变得更小了。将这种现象称为精度丢失因为float型数据能够表示的有效数组为7位最多只保证1.234567e10的正确性要使结果正确就要把a和b改为double型因为double可以表示的精度位15-16位。
【例】验证精度丢失现象的程序。
// float double
#include stdio.hint main(){float a 1.23456789e10; // 赋值的一瞬间发生精度丢失因为浮点常量默认是8个字节存储double型。float的有效数字精度是67位float b;b a 20; // 计算时精度丢失printf(a%f\n,a); // 既可以输出float也可以输出double类型printf(b%f\n,b);double c 1.23456789e10;double d;d c 20;printf(c%f\n,c);printf(d%lf\n,d);return 0;
}double输出类型lf
scanf读取double类型时要用lf如double d;scanf(%lf,d);
另外针对强制类型转换int转float可能造成精度丢失因为int是有10位有效数字的但是int强制转为double不会float转为double也不会丢失精度。
【20.6 题】
1、真题2010年14题假定变量i、f和d的数据类型分别为int,float,doubleint用补码表示float和double分别用IEEE754单精度和双精度浮点数格式表示已知i785,f1.5678e3,d1.5e100.若在32位机器中执行下列关系表达式下面四个表达式结果均为真。i(int)(float)i真. f(float)(int)f假转换为int类型时精度丢失. f(float)(double)f真. (df)-df假
解释题中是那种数据类型转换的顺序为int-float-double,若将float转换为int小数位部分会被舍去int是精确到32位的整数而float只保存到132位因此一个32位的int整数在转换为float时会有损失。但i是785只有3位低于浮点精度表示的6-7位。
将float型的f转换为int型小数点后的数位丢失1567.81.5678e3就是1567.8会变为1567与原有的1567.8不相等结果为非真。
double的精度和范围都比float大float转换为double不会有损失。
浮点运算df时需要对阶对阶后f的位数有效位被舍去而变为0对阶就是从左边开始浮点数d有10的100次幂了而浮点数f在数的地位double有效位数只有15-16位自然对阶时低位直接忽略掉了10的100次幂到85次幂之间的有效位数才是double要保存的因此df仍然位d再减去d后结果为0因为double只能15位有效数字结果非真。根据不同类型数据混合运算“类型提升”原则(df)-df等号左边的类型位double型结果非真。
注从int转换为float时虽然不会发生溢出但由于位数位数的关系可能有效数据舍入影响精度而转换为double则能保留精度。
对阶对阶的原则是小阶向大阶方向化误差比较小。之所以这样做是因为若大阶对小阶则位数的数值部分的高位需移出而小阶对大阶移出的是位数的数值部分的低位这样损失的精度更小。
2、(真题2013年13题某数采用IEEE754单精度浮点数格式表示为C640 0000H则该数的值是-1.5*2^12错误。值为-1.5*2^13
解析C640 0000H
1 100 0110 0 100 0000
符号位1:负
指数部分100 0110 0 2^7 2^32^2 - 127 184 13 1000 1100 - 0111 1111
1000 1100 1000 0001 1000 1101 -(841) 13
小数部分100 0000 1.1 1.5
位数有隐含位要加1. 3、2014年14题float型数据常用IEEE754单精度浮点格式表示假设两个float型变量x和y分别存放在32位寄存器f1和f2中若(f1)CC90 0000H,(f2)B0C0 0000H,则x和y之间的关系为xy且符号相同。
解析
f1 1100 1100 1001 0000 。。。。
f2 1011 0000 1100 0000 。。。。
f1的指数部分1001 1001 2^72^42^31 - 127 2 16 8 26
f2的指数部分0110 0001 2^6 2^5 1 64321 97 - 127 -30
f1的小数部分1.001 加上符号位 -1.001 * 2^26
f2的小数部分1.1 加上符号位 - 1.1*2^-30
1.001 * 2^26 1.1*2^-30. -1.001 * 2^26 -1.1*2^-30.
f1和f2对应的二进制分别是。。根据IEEE754浮点数标准可知f1的数符位1阶码位1001 1001位数为1.001f2的数符位1阶码位0110 0001位数为1.1则可知两数均为负数符号相同。f1的绝对值为1.001*2^26,f2的绝对值为1.1*2^-30,则f1的绝对值比f2的绝对值大而符号为负真值大小相反即f1的真值比f2的真值小即xy。
【20.7 选择题真题讲解】
2012年
13.假定编译器规定int和short型长度分别为32位和16位执行下列C语言语句unsigned short x 65530;unsigned int y x;得到y的机器数为。
xff fa y0000 fffaH
解析将一个16位unsigned short转换成32位形式的unsigned int因为都是无符号数新表示形式的高位用0填充。16位无符号整数所能表示的最大值为65535其十六进制表示为FFFFH故x的十六进制表示为FFFFH-5H FFFAH所以y的十六进制表示为0000 FFFAH。
14.float类型即IEEE754单精度浮点数格式能表示的最大正整数是。
解析IEEE754单精度浮点数是尾数采取隐藏位策略的原码表示且阶码用移码偏置值为127表示的浮点数。规格化的短浮点数的真值为(1)^S*1.m*2^E-127,S为符号位阶码E的取值为1-2548位表示尾数m为23位共32位故float类型能表示的最大整数是1.111...1*2^254-1272^127*(2-2^-23) 2^128 - 2^104.
1.111..1 * 2^(254-127)1.111...1*2^127(24个1)*2^(127-23)(2^24-1)*2^1042^128-2^104.
【另解】IEEE754单精度浮点数的格式如下图所示 当表示最大正整数时数符取0阶码取最大值为127尾数部分隐含了整数部分的“1”23位尾数全取1时尾数最大为2-2^-23此时浮点数的大小为2-2^-23)*2^1272^128-2^104
2013年
14.某字长为8位的计算机中已知整型变量xy的机器数分别为[x]补1111 0100,[y]补1011 0000.若整型变量z2*xy/2则z的机器数为
解析乘以左移除以右移
2*x 1110 1000
y/2 1101 1000
z 1100 0000 C0H
x原码1000 1100 -12*2 -24
y原码1101 0000 -(2^6 2^4) -(6416) -80/2 -40
2*x将x算术左移一位为1110 1000y/2将y算术右移一位为1101 1000均无溢出或丢失精度。补码相加为1110 1000 1101 1000 1 100 0000亦无溢出。也可以看x的值为-12y的值为-80计算后是-64对应的编码就是1100 0000.
2016年
13.有如下C语言程序段short si -32767; unsigned short usi si;执行上述两条语句后usi的值为
解析
si补码机器表示 1000 0000 0000 0001
usi 1000 0001 2^15 1 32768 1 32769
short为16位因C语言中的数据再内存中位补码表示形式si对应的补码二进制表示为 1000 0000 0000 0001B最前面的一位“1”为符号位表示负数即-32767。由signed型转化为登场unsigned型数据时符号位称为数据的一部分负数转化为无符号数即正数其数值将发生变化。usi对应的补码二进制表示与si的表示相同但表示正数为32769.
14.某计算机字长为12位按字节编址采用小端Little Endian方式存放数据。假定有一个double型变量某机器数表示为1122 3344 5566 7788.存放在0000 8040H开始的连续存储单元中则存储单元0000 8046H中存放的是
解析小端方式存储数据低位在前高位在后低位在低地址高位在高地址。
机器数88 77 66 55 44 33 22 11
0000 8040H88
0000 8041H77
0000 8042H66
0000 8043H55
0000 8044H44
0000 8045H33
0000 8046H22 即为答案
大端方式一个字中的高位字节Byte存放在内存中这个字区域的低地址处。小端方式一个字中的低位字节Byte存放在内存中这个字区域的低地址处。依次分析各自节的存储分配如下表所示 从而存储单元0000 8046H存放的是22H。
2018年
13.假定带符号整数采用补码表示若int型变量x和y的机器数分别是FFFF FFDFH和0000 0041H则x、y的值以及x-y的机器数分别是
解析
x补 FFFF FFDFH x的原码1000 0021 -2*161 -33
y 0000 0041H 4*161 65 0100 0001
x-y -98
-y补 FFFF FFBFH - 1011 1111
x的补码1101 1111
y的补码1011 1111
x-y的补码机器数1001 1110 9E
利用补码转换成原码的规则负数符号位不变数值位取反加1整数补码等于原码。两个机器数对应的原码是[x]原 .... 0021H对应的数值是-33[y]原[y]补.... 0041H 65。x-y直接利用补码减法准则[x]补-[y]补[x]补[-y]补-y的补码连同符号位取反加1最终减法变成加法得出结果FFFF FF9EH.
14.IEEE754单精度浮点格式表示的数中最小的规格化整数是。
解析IEEE754单精度浮点数的符号位、阶码位、尾数位省去正数位1所占的位数分别是1、8、23位。最小正数数符位取0移码的取值范围是1254取1的阶码值1-127-126127为规定的偏置值尾数取全0最终推出最小规格化正数为1.0*2^-126。
1.000...023个0小数部分全0
1.0 * 2^(1-127) 指数部分最小指数部分的范围是1-254
1.0*2^-126
15.某32位计算机按字节编址采用小端Little Endian方式。若语令“int i 0;对应指令的机器代码为“C7 45 FC 00 00 00 00”则语句“int i -64;对应指令的机器代码是C7 45 FC C0 FF FF FF.
解析
-64补 64的原码0100 0000取反1100 0000 FF FF FF C0
需要转换成小端存储方式C0 FF FF FF.
按字节编址采用小端方式低位的数据存储在低地址位、高位的数据存储在高地址位并且按照一个字节相对不变的顺序存储。存储0的位数是后32位那么只需要把-64的补码按字节存储在其中即可-64表示成32位的十进制数是FF FF FF C0根据小端方式的特点高字节存储在低地址就是C0 FF FF FF.
16.整数x的机器数为1101 1000分别对x进行逻辑右移和算术右移1位操作得到的机器数各是
解析逻辑右移0110 1100算术右移1110 1100
逻辑移位左移和右移空位都补0并且所有数组参与移动。算术一位符号位不参与移动右移空位补符号位左移空位补0.
2019年
13.考虑以下C语言代码unsigned short usi 65535;short si usi;执行上述程序段后si的值是-1。
解析usi 无符号短整型 1111 1111 1111 1111
si短整型 补码 取反符号位保持不变其余位取反1000 0000 0000 0000 加1符号位不变加1:1000 0000 0000 0001 -1
unsigned short类型位无符号短整型长度为2字节因此unsigned short usi转换为二进制代码即1111 1111 1111 1111.short类型位短整型长度位2字节在采用补码的机器上short si的二进制代码为1111 1111 1111 1111因此si的值为-1。
【20 代码题】
浮点数4.5的指数部分的值为2129-127得到小数部分是001 0000 0000 0000 0000 0000 0000 0000里边1的个数只有1个那么输出1总计的输出就是2 1每个数占用3个字符位置%3d。现在输入的浮点数是1.456那么需要通过单步调试看看内存算一算1.456的指数部分是多少小数部分1的个数数一数然后输出 【第21节 汇编语言零基础入门】
【21.2 与408关联】
1 与408关联
2017年44题
44.10分在按字节编址的计算机M上题43中f1的部分源程序阴影部分与对应的机器级代码包括指令的虚拟地址如下 ————————————
仅用于本人学习
来源网络 文章转载自: http://www.morning.tqklh.cn.gov.cn.tqklh.cn http://www.morning.fbzdn.cn.gov.cn.fbzdn.cn http://www.morning.yrlfy.cn.gov.cn.yrlfy.cn http://www.morning.wcjk.cn.gov.cn.wcjk.cn http://www.morning.gslz.com.cn.gov.cn.gslz.com.cn http://www.morning.mfqmk.cn.gov.cn.mfqmk.cn http://www.morning.qdzqf.cn.gov.cn.qdzqf.cn http://www.morning.rxwnc.cn.gov.cn.rxwnc.cn http://www.morning.mghgl.cn.gov.cn.mghgl.cn http://www.morning.spkw.cn.gov.cn.spkw.cn http://www.morning.mspqw.cn.gov.cn.mspqw.cn http://www.morning.mlycx.cn.gov.cn.mlycx.cn http://www.morning.hfbtt.cn.gov.cn.hfbtt.cn http://www.morning.wsxxq.cn.gov.cn.wsxxq.cn http://www.morning.amlutsp.cn.gov.cn.amlutsp.cn http://www.morning.ntqlz.cn.gov.cn.ntqlz.cn http://www.morning.snnkt.cn.gov.cn.snnkt.cn http://www.morning.zxwqt.cn.gov.cn.zxwqt.cn http://www.morning.ngzkt.cn.gov.cn.ngzkt.cn http://www.morning.mbaiwan.com.gov.cn.mbaiwan.com http://www.morning.kqzt.cn.gov.cn.kqzt.cn http://www.morning.kdnbf.cn.gov.cn.kdnbf.cn http://www.morning.touziyou.cn.gov.cn.touziyou.cn http://www.morning.nlcw.cn.gov.cn.nlcw.cn http://www.morning.rwmp.cn.gov.cn.rwmp.cn http://www.morning.gxfzrb.com.gov.cn.gxfzrb.com http://www.morning.kdldx.cn.gov.cn.kdldx.cn http://www.morning.pqsys.cn.gov.cn.pqsys.cn http://www.morning.drpbc.cn.gov.cn.drpbc.cn http://www.morning.yfpnl.cn.gov.cn.yfpnl.cn http://www.morning.qhmhz.cn.gov.cn.qhmhz.cn http://www.morning.lgnbr.cn.gov.cn.lgnbr.cn http://www.morning.bwmm.cn.gov.cn.bwmm.cn http://www.morning.cqyhdy.cn.gov.cn.cqyhdy.cn http://www.morning.qsctt.cn.gov.cn.qsctt.cn http://www.morning.glbnc.cn.gov.cn.glbnc.cn http://www.morning.cpqwb.cn.gov.cn.cpqwb.cn http://www.morning.xnltz.cn.gov.cn.xnltz.cn http://www.morning.tqjks.cn.gov.cn.tqjks.cn http://www.morning.dlurfdo.cn.gov.cn.dlurfdo.cn http://www.morning.zycll.cn.gov.cn.zycll.cn http://www.morning.prfrb.cn.gov.cn.prfrb.cn http://www.morning.dkzrs.cn.gov.cn.dkzrs.cn http://www.morning.pzjfz.cn.gov.cn.pzjfz.cn http://www.morning.mkfhx.cn.gov.cn.mkfhx.cn http://www.morning.cnkrd.cn.gov.cn.cnkrd.cn http://www.morning.vnuwdy.cn.gov.cn.vnuwdy.cn http://www.morning.ygqjn.cn.gov.cn.ygqjn.cn http://www.morning.knpmj.cn.gov.cn.knpmj.cn http://www.morning.ldqzz.cn.gov.cn.ldqzz.cn http://www.morning.nlhcb.cn.gov.cn.nlhcb.cn http://www.morning.zbpqq.cn.gov.cn.zbpqq.cn http://www.morning.rqxmz.cn.gov.cn.rqxmz.cn http://www.morning.snzgg.cn.gov.cn.snzgg.cn http://www.morning.lxhrq.cn.gov.cn.lxhrq.cn http://www.morning.yhwxn.cn.gov.cn.yhwxn.cn http://www.morning.rqgjr.cn.gov.cn.rqgjr.cn http://www.morning.tnkwj.cn.gov.cn.tnkwj.cn http://www.morning.tbqxh.cn.gov.cn.tbqxh.cn http://www.morning.qtzk.cn.gov.cn.qtzk.cn http://www.morning.jrhmh.cn.gov.cn.jrhmh.cn http://www.morning.drwpn.cn.gov.cn.drwpn.cn http://www.morning.kysport1102.cn.gov.cn.kysport1102.cn http://www.morning.sqlh.cn.gov.cn.sqlh.cn http://www.morning.psxwc.cn.gov.cn.psxwc.cn http://www.morning.rlcqx.cn.gov.cn.rlcqx.cn http://www.morning.xhddb.cn.gov.cn.xhddb.cn http://www.morning.xkhxl.cn.gov.cn.xkhxl.cn http://www.morning.dqwykj.com.gov.cn.dqwykj.com http://www.morning.amlutsp.cn.gov.cn.amlutsp.cn http://www.morning.rmqlf.cn.gov.cn.rmqlf.cn http://www.morning.bpttm.cn.gov.cn.bpttm.cn http://www.morning.hrydl.cn.gov.cn.hrydl.cn http://www.morning.wnkbf.cn.gov.cn.wnkbf.cn http://www.morning.htsrm.cn.gov.cn.htsrm.cn http://www.morning.cptzd.cn.gov.cn.cptzd.cn http://www.morning.glpxx.cn.gov.cn.glpxx.cn http://www.morning.rsnn.cn.gov.cn.rsnn.cn http://www.morning.qmtzq.cn.gov.cn.qmtzq.cn http://www.morning.fthcn.cn.gov.cn.fthcn.cn