【CSAPP】家庭作业2.55~2.76

2.55*

:在你能访问的不同的机器上,编译show_bytes.c并运行代码,确定这些机器的字节顺序。

// show_bytes.c
#include <stdio.h>

typedef unsigned char *byte_pointer;

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

void show_int(int x)
{
   
	show_bytes((byte_pointer)&x, sizeof(int));
}

x86_64上,运行结果为:

// show_int(0x87654321);
[liheng@localhost2 2]$ ./a.out 
21 43 65 87 

低位字节保存在低地址,该机器按小端顺序存储多字节对象。

2.56*

:试着用不同的示例值来运行show_bytes.c

// show_int(0x11223344);
[liheng@localhost2 2]$ ./a.out 
44 33 22 11 
// show_int(0x22);
[liheng@localhost2 2]$ ./a.out 
22 00 00 00 
// show_int(0x11000000);
[liheng@localhost2 2]$ ./a.out 
00 00 00 11 

2.57*

:编写并运行程序show_shortshow_longshow_double

void show_short(short x)
{
   
	show_bytes((byte_pointer)&x, sizeof(short));
}

void show_long(long x)
{
   
	show_bytes((byte_pointer)&x, sizeof(long));
}

void show_double(double x)
{
   
	show_bytes((byte_pointer)&x, sizeof(double));
}

x86_64上,运行结果为:

// show_short(0x1234);
// show_long(0x1234);
// show_double(0x1234);
[liheng@localhost2 2]$ ./a.out 
34 12 
34 12 00 00 00 00 00 00 
00 00 00 00 00 34 B2 40 
// show_short(0x1030);
// show_long(0x1030);
// show_double(0x1030);
[liheng@localhost2 2]$ ./a.out 
30 10 
30 10 00 00 00 00 00 00 
00 00 00 00 00 30 B0 40 

2.58**

:编写过程is_little_endian,当在小端法机器上运行时返回1,否则返回0

int is_little_endian()
{
   
	uint32_t x = 0x12345678; // #include <stdint.h>
	return *(uint8_t *)&x == (uint8_t)0x78;
}

x86_64上,运行结果为:

// printf("is_little_endian: %d\n", is_little_endian());
[liheng@localhost2 2]$ ./a.out 
is_little_endian: 1

2.59**

:编写一个C表达式,它生成一个字,由x的最低有效字节和y中剩下的字节组成。对于x = 0x89ABCDEFy = 0x76543210得到0x765432EF
:表达式为(x & 0xFF) | (y & ~0xFF)

2.60**

:假设我们将一个w位的字中的字节从0(最低位字节)到w / 8 - 1(最高位字节)编号,写出下面C函数的代码,它会返回一个无符号值,其中参数x的字节i被替换成字节b

unsigned replace_byte(unsigned x, int i, unsigned char b);
// replace_byte(0x12345678, 2, 0xAB) --> 0x12AB5678
// replace_byte(0x12345678, 0, 0xAB) --> 0x123456AB


replace_byte的实现:

unsigned replace_byte(unsigned x, int i, unsigned char b)
{
   
	unsigned bits = i << 3;
	unsigned x1 = x & ~(0xFF << bits);
	unsigned b1 = b << bits;
	return x1 | b1;
}

x86_64上的运行结果:

// printf("%p\n", replace_byte(0x12345678, 4, 0xAB));
// printf("%p\n", replace_byte(0x12345678, 3, 0xAB));
// printf("%p\n", replace_byte(0x12345678, 2, 0xAB));
// printf("%p\n", replace_byte(0x12345678, 1, 0xAB));
// printf("%p\n", replace_byte(0x12345678, 0, 0xAB));
[liheng@localhost2 2]$ ./a.out 
0x123456ab
0xab345678
0x12ab5678
0x1234ab78
0x123456ab

位级整数编码规则

在接下来的作业中,我们特意限制了你能使用的编程结构,来帮助你更好地理解C语言的位级、逻辑和算术运算。你的代码必须遵守以下规则:

  • 假设
  1. 整数用补码形式表示。
  2. 有符号数的右移是算术右移。
  3. 数据类型intw(一定是8的整数倍)位长的。某些题目会给出w的值。
  • 禁止使用
  1. 条件语句if? : 、循环、分支语句、函数调用和宏调用。
  2. 除法、模运算和乘法。
  3. 相对比较运算<><=>=
  • 允许的运算
  1. 所有的位级和逻辑运算。
  2. 左移和右移,位移量只能在0 ~ w-1之间。
  3. 加法和减法。
  4. 相等==和不相等!=
  5. 整型常数INT_MININT_MAX
  6. intunsigned进行隐式或显式强制类型转换。

个别题目有特殊的限制。

2.61**

:写一个C表达式,在下列描述的条件下产生1,在其他情况下得到0,假设xint类型。

  1. x的任何位都等于1
!~x
  1. x的任何位都等于0
!x;
  1. x的最低有效字节中的位都等于1
!~(x | ~0xFF)
  1. x的最高有效字节中的位都等于0
!((0xFF << ((sizeof(int) - 1) << 3)) & x);

2.62***

:编写一个函数int_shifts_are_arithmetic(),在对int类型的数使用算术右移的机器上运行时这个函数返回1,其他情况下返回0

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值