第二章家庭作业
说明:使用的64位小端机。
2.55-2.57
2.55-2.57的答案写到一起
//
// Created by Gong on 2022/8/2.
//
#include <stdio.h>
typedef unsigned char *byte_pointer;
void show_bytes(byte_pointer start,size_t len){
//todo size_t
for (size_t i=0;i<len;i++){
printf("%.2x ",start[i]);
}
printf("\n");
}
void show_short(short x){
show_bytes((byte_pointer)&x,sizeof(short));
}
void show_int(int x){
show_bytes((byte_pointer)&x,sizeof (int ));
}
void show_long(long x){
show_bytes((byte_pointer)&x,sizeof(long));
}
void show_float(long x){
show_bytes((byte_pointer)&x,sizeof(long));
}
void show_double(double x){
show_bytes((byte_pointer)&x,sizeof(double ));
}
void show_long_double(double x){
show_bytes((byte_pointer)&x,sizeof(long double ));
}
int main() {
show_short(0x1234); //34 12
show_int(0x1234); //34 12 00 00
show_long(0x1234); //34 12 00 00 00 00 00 00
printf("浮点数:\n");
show_float(0x1234); //34 12 00 00 00 00 00 00
show_double(0x1234);//00 00 00 00 00 34 b2 40
show_long_double(0x1234);//00 00 00 00 00 34 b2 40 40 07 0a e6 fe 7f 00 00
return 0;
}
输出:
2.58
编写过程i s _ l i t t l e _ e n d i a n ,当在小端法机器上编译和运行时返回1 ,在大端法机器上编译运行时则返回0 。这个程序应该可以运行在任何机器上,无论机器的字长是多少。
#include <stdio.h>
int is_little_endian() {
int x = 1;
char y = (char) x;
printf("y:%d\n", y);//:y:1
return y;
}
int main() {
is_little_endian();
return 0;
}
2.59
编写一个C表达式,它生成一个字,由x的最低有效字节和y中剩下的字节组成。对于运算数x= O x 8 9 A B C D E F和y = O x 7 6 5 4 3 2 1 0 ,就得到O x 7 6 5 4 3 2 E F。
第一版是自己写的,第二版是网上找到的不错的写法。
第一版:
#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));
}
//最大的无符号int
const unsigned int unsigned_int_max = -1; //ffffffff
//低字节掩码
const int mask_low = 0xFF; //000000ff
//较高字节掩码
const int mask_heigh = unsigned_int_max ^ mask_low;//ffffff00 低字节位为0,其余位全为1;
int maskValue(int x, int y) {
int tempx = x & mask_low;
int tempy = y & mask_heigh;
show_int(tempx); //ef000000
show_int(tempy); //00325476
int res = tempx | tempy;
show_int(res); //ef325476
return res;
};
int main() {
// show_int(unsigned_int_max);
// show_int(mask_low); //ff000000
// show_int(mask_heigh); //00ffffff
maskValue(0x89ABCDEF, 0x76543210);
}
第二版:
//
// Created by Gong on 2022/7/16.
//
#include <stdio.h>
int main() {
unsigned x = 0x89ABCDEF;
unsigned y = 0x76543210;
unsigned num = (x & 0xff) | (y & ~0xFF);
printf("%X\n", num); //765432EF
}
2.60
假设我们将一个w位的字中的字节从0 ( 最低位)到w/ 8 - l (最高位)编号。写出下面C函数的代码,它会返回一个无符号值,其中参数x的字节i 被替换成字节b :
unsigned replace_byte (unsigned x, inti, unsigned char b);
以下示例,说明了这个函数该如何工作:
对于0x12345678来说,78:第0位,56:第1位,34:第2位
replace_byte(Ox12345678, 2, OxAB) --> Ox12AB5678
replace_byte(Ox12345678, 0, OxAB) --> Ox123456AB
//
// Created by Gong on 2022/7/16.
//
#include <stdio.h>
typedef unsigned char * byte_pointer;
/**
* 思路:
* 先将第i位的byte(后面简称为第i位)设置为0
* 再将第i位设置为b对应的值
*/
void replace_byte(unsigned x,int i ,unsigned b){
unsigned mask_low = 0xFF << i*8;//FF0000
printf("mask_low:%X\n",mask_low);
unsigned mask_full = ~0;//FFFFFFFF
printf("mask_full:%X\n",mask_full);//FF00FFFF
unsigned mask=mask_low ^ mask_full;//12AB5678
printf("mask:%X\n",mask);
//将第i位的byte置0
x = x & mask;
//将b移动到第i
b<<=i*8;
unsigned res ;
//设置x的第i位
res = x | b;
printf("res:%X\n",res); //12AB5678
}
int main(){
unsigned x= 0x12345678;
int i = 2;
unsigned b = 0xAB;
replace_byte(x,i,b);
}
第二版:网上找到的不错的写法:
#include <stdio.h>
int replaced_byte(unsigned x, unsigned char b, int i)
{
int i_times_8 = i << 3;
unsigned mask = 0xFF << i_times_8;
return (x & ~mask) | (b << i_times_8);
/* one-line compact version */
//return ( x & ~(0xFF << (i << 3))) | (b << (i << 3));
}
int main(){
int assert_result;
assert_result = 0x12AB5678;
// 这里用 !(a^b) 来判断两个数是否相等——如果相等,两个数的异或结果位0
!(assert_result ^ replaced_byte(0x12345678, 0xAB, 2)) &&
(printf("First example test successful!\n"));
assert_result = 0x123456AB;
!(assert_result ^ replaced_byte(0x12345678, 0xAB, 0)) &&
(printf("Second example test successful!\n"));
}
2.61
//
// Created by Gong on 2022/8/15.
//
#include <stdio.h>
static void echo(char *str){
printf("%s\n",str);
}
int test_option_a(int x){
return !~x; //这里的!是为了得到布尔值
}
int test_option_b(int x){
return !x;
}
int test_option_c(int x){
return !(x^0xff);
}
int test_option_d(int x){
int w = sizeof(int) << 3;// <<3 表示乘以2^3=8
int y = 0xff<<(w-8);
return !(x^ y);
}
int main(){
int w = sizeof(int) <<3;// <<3 表示乘以2^3=8
int any_bit_eql_1 = ~0;
int any_bit_eql_0 = 0;
int any_bit_in_lsb_eql_1 = 0xFF; //least significant byte
int any_bit_in_msb_eql_0 = 0xFF <<(w - 8); //most significant byte
(test_option_a(any_bit_eql_1)) && (printf("Option A pass\n"));
(test_option_b(any_bit_eql_0)) && (printf("Option B pass\n"));
(test_option_c(any_bit_in_lsb_eql_1)) && (printf("Option C pass\n"));
(test_option_d(any_bit_in_msb_eql_0)) && (printf("Option D pass\n"));
printf("%d",!(0x0f&0xff));
}
2.62
第一版:
//
// Created by Gong on 2022/8/5.
//
#include <stdio.h>
int int_shifts_are_arithmetic() {
int w = sizeof(int) * 8;
int x = -1;
return !!(x >> w); //!!是为了取得bool值,可以省略
}
int main() {
int_shifts_are_arithmetic() && printf("机器使用算数右移");
}
第二版
网上找的不错的参考
//
// Created by Gong on 2022/8/5.
//
#include <stdio.h>
int int_shifts_are_arithmetic() {
int x = ~0;
return (x >> 1) == x;
}
int int_shifts_are_logical() {
int x = ~0;
x >>= 1;
return !!(~x);
}
int main() {
int_shifts_are_arithmetic() && printf("机器使用算数右移");
int_shifts_are_logical() && printf("机器使用逻辑右移");//本人未在使用逻辑右移的机器上测试
}