20155212 ch02 课下作业

20155212 ch02 课下作业

T1

  • 题目

    参考附图代码,编写一个程序 “week0601学号.c",判断一下你的电脑是大端还是小端

  • 相关知识

    • 小端法:最低有效字节在最前面
    • 大端法:最高字节在最前面
  • 思路

    • 将参数的指针强制类型转换为unsigned char *代码利用强制转换类型告诉机器,程序应该把这个指针看成指向一个字节序列,而不是指向一个原始数据类型的对象。然后这个指针会被看成是对象使用的最低字节地址。
  • 代码

#include <stdio.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, size_t len) {
	size_t i;
	for(i=0; i<len; i++)
		printf(" %.2x", start[i]);
	printf("
");
}

void show_int(int x) {
	show_bytes((byte_pointer) &x, sizeof(int));20155212 ch02 课下作业
}

void show_float(float x) {
	show_bytes((byte_pointer) &x, sizeof(float));
}

void show_pointer(void  *x) {
	show_bytes((byte_pointer) &x, sizeof(void *));
}

void test_show_bytes(int val) {
	int ival=val;
	float fval=(float)ival;
	int *pval=&ival;
	show_int(ival);
	show_float(fval);
	show_pointer(pval);
}

void main() {
	int val;
	scanf("%d", &val);
	test_show_bytes(val);
}
  • 运行结果

  • 结果分析

    参数12345的十六进制表示应该是0x00003039,但是实际显示最低有效字节0x39最先输出,说明这是小端机器。

T2

  • 题目
    1. 调用附图代码,编写一个程序 “week0602学号.c",用show_int(), show_float()打印一下你的4位学号,参考教材P33打印出匹配的位序列
    2. 参考教材p82,给出出匹配的位序列的推导过程
  • 相关知识
    • 如何输出位序列。(代码如下)
int i, j;
for(i=0; i<11; i++)
	printf(" ");
for(i=0; i<len; i++){
	for(j=0; j<8; j++){
		printf("%d", (start[i]>>j) & 0x1);
	}
}
printf("
");
- IEEE浮点表示

  • 代码
#include <stdio.h>
#include <stdlib.h>

typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, size_t len) {
	size_t i;
	for(i=0; i<len; i++)
		printf(" %.2x", start[i]);
	printf("
");
}

void show_int(int x) {
	size_t len=sizeof(int);
	show_bytes((byte_pointer) &x, len);
	byte_pointer start=(byte_pointer) &x;
	int i, j;
	for(i=0; i<11; i++)
		printf(" ");
	for(i=0; i<len; i++){
		for(j=0; j<8; j++){
			printf("%d", (start[i]>>j) & 0x1);
		}
	}
	printf("
");
}

void show_float(float x) {
	size_t len=sizeof(float);
	show_bytes((byte_pointer) &x, len);
	byte_pointer start=(byte_pointer) &x;
	int i, j;
	for(i=0; i<len; i++){
		for(j=0; j<8; j++){
			printf("%d", (start[i]>>j) & 0x1);
		}
	}
	printf("
");
}

void show_pointer(void  *x) {
	show_bytes((byte_pointer) &x, sizeof(void *));
}

void test_show_bytes(int val) {
	int ival=val;
	float fval=(float)ival;
	int *pval=&ival;
	show_int(ival);
	int i;
	for(i=0;i<11;i++){
		printf(" ");
	}
	for(i=0;i<13;i++)
		printf("*");
	printf("
");
	show_float(fval);
}

void main() {
	int val;
	scanf("%d", &val);
	test_show_bytes(val);
}
  • 运行结果

  • 推导

    5212具有二进制表示[1010001011100],将二进制小数点左移13位,得到规格化表示1.010001011100 x 2^13。为了用IEEE单精度形式编码,舍弃开头的1,并在末尾增加10个0,来构造小数字段,得到二进制表示[10100010111000000000000]。为了构造阶码字段,用13加上偏置量127,得到140,其二进制表示为[10001100],加上符号位0,即可得到二进制的浮点表示[01000101101000101110000000000000]。

T3

  • 题目

    1. 编写一个程序 “week0603学号.c",运行下面代码:

      1  short int v = -学号后四位
      2  unsigned short uv = (unsigned short) v
      3  printf("v = %d,  uv = %u
       ", v, uv);
      
    2. 在第三行设置断点用gdb调试,用p /x v; p /x uv 查看变量的值,提交调试结果截图,要全屏,要包含自己的学号信息

    3. 分析p /x v; p /x uv 与程序运行结果的不同和联系

  • 相关知识

    • 有符号和无符号数之间的转换
      • C语言允许在各种不同的数字数据类型之间做强制类型转换。
      • 强制类型转换的结果保持位值不变,只是改变了解释这些位的方式。
    • gdb调试
      • b (line number):设置行断点
      • run:运行
      • p:print
      • /x:十六进制
  • 代码

#include<stdio.h>

void main(){
	short int v = -5212;
	unsigned short uv = (unsigned short) v;
	printf("v = %d,  uv = %u
 ", v, uv);
}
  • 运行结果

  • 分析

    数值可能会改变,但是位模式不变

P97 2.96

  • 题目
  • 相关知识
    - IEEE浮点表示
  • 代码
#include <stdio.h>

typedef unsigned float_bits;

int float_f2i(float_bits f){
    unsigned sign, exp, frac, last_bit;
    int i;
    sign = f >> 31;
    exp = (f >> 23) & 0xff;
    frac = f & 0x7fffff;
    if (exp == 158 && frac == 0 && sign == 1)
        i = 0x80000000;
    else if (exp > 157 || exp == 0xff)
        i = 0x80000000;
    else if (exp < 126)
        i = 0;
    else{
        exp -= 127;
        frac |= 0x800000;
        if (exp > 23){
            exp -= 23;
            frac <<= exp;
        }else if (exp < 23){
            exp = 23 - exp;
            frac >>= exp;
        }
        if (sign == 1)
            i = (~frac) + 1;
        else
            i = frac;
    }
    return i;
}
void main(){
	float f;
    unsigned i;
    int j, k;
    
    for (i = 0x3fbfff70U; i <= 0xffffffffU; i++)
    {
        f = *(float *)&i;
        j = (int)f;
        k = float_f2i(i);
        printf("原值:%f 	 机器运算:%d 	 函数运算:%d
", f, j, k);
    }
}
  • 运行结果

P97 2.97

  • 题目
  • 代码
#include <stdio.h>

typedef unsigned float_bits;
typedef unsigned char *byte_pointer;

void show_bytes(byte_pointer start, size_t len) {
	size_t i;
	for(i=0; i<len; i++)
		printf(" %.2x", start[i]);
	printf("	");
}

float_bits float_i2f(int x) {
	unsigned shiftLeft=0;  
	unsigned afterShift, tmp, flag;  
	unsigned absX=x;  
    unsigned sign=0;  
    if (x==0) 
    	return 0;  
    if (x<0){  
        sign=0x80000000;  
        absX=-x;  
    }  
    afterShift=absX;  
    while (1){
    	tmp=afterShift;
    	afterShift<<=1;
    	shiftLeft++;  
		if (tmp & 0x80000000) 
			break;  
    }
    if ((afterShift & 0x01ff)>0x0100)  
		flag=1;  
    else if ((afterShift & 0x03ff)==0x0300)  
		flag=1;  
    else  
		flag=0;  
	return sign+(afterShift>>9)+((159-shiftLeft)<<23)+flag;
}


void main(){
    int x;
    unsigned i,k;
    float j;

    for (i = 0x3fbfff70U; i <= 0xffffffffU; i++){
        x = *(int *)&i;
        printf("原值:");
        show_bytes((byte_pointer) &x, sizeof(int));
        j=(float)i;
        printf("机器运算:");
        show_bytes((byte_pointer) &j, sizeof(float));
        k=float_i2f(i);
        printf("函数运算:");
        show_bytes((byte_pointer) &k, sizeof(unsigned));
        printf("
");
    }
}

  • 运行结果
原文地址:https://www.cnblogs.com/dky20155212/p/7751945.html