第二章 信息的表示和处理
2-55 ~ 2-57
头文件show_bytes.c
1 2 3 4 5 6 7 8 9 10 11 #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 ("\n" ); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 #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 ("\n" ); } void show_int (int x) { show_bytes((byte_pointer) &x, sizeof (int )); } 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 )); } void show_pointer (void *x) { show_bytes((byte_pointer) &x, sizeof (void *)); } void test_show_bytes (int val) { int ival = val; short sval = (short ) ival; long lval = (long ) ival; double dval = (double ) ival; int *pval = &ival; show_int(ival); show_short(sval); show_long(lval); show_double(dval); show_pointer(pval); } int main () { test_show_bytes(12345 ); }
show_bytes
打印出每个以十六进制表示的字节。
上面程序使用强制类型转换来访问和打印不同程序对象的字节表示。
我们将byte_pointer
定义为一个指向类型为unsigned char
的对象指针,这样一个字节指针引用一个字节序列,其中每个字节都被认为是一个非负整数。该字节数指定为数据类型size_t
,表示数据结构大小的首选数据类型。
c格式化指针
"%.2x"
表明整数必须用至少两个数字的十六进制格式输出
sizeof(T)
返回存储一个类型为T
的对象所需要的字节数。需要注意的是sizeof
不是一个固定的值,在不同机器上可能会不同
输出十六进制:
39300000 3930 3930000000000000 00000000801cc840 e8c779b7f77f0000
2-58
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <stdio.h> typedef unsigned char * byte_pointer;int is_litter_endian () { int test = 0x01 ; byte_pointer p = (byte_pointer) & test; if (*p) return 1 ; else return 0 ; } int main () { return is_litter_endian(); }
编译运行
1 gcc 2_58.c && ./a.out ; echo $?
输出
1
2-59
很明显我们只需要
ox89ABCDEF & 0xFF = 0x000000EF
0x76543210 & ~0xFF = 0x76543200
最后
0x000000EF | 0x76543200 = 0x765432EF
1 2 3 4 5 6 7 #include <stdio.h> int main () { int x = 0x89ABCDEF ; int y = 0x76543210 ; printf ("0x%.8x\n" , (x & 0xff ) | (y & ~0xff )); }
编译运行
输出
0x765432ef
2-60
为了使replace_byte(0x12345678, 2, 0xAB) --> 0x12AB5678
我们先算出左移的位,也就是move = 2 * 8 = 16
x & ~(0xff << move)
=
0x12005678
b << move = 0xAB0000
0x12005678 | 0xAB0000 = 0x12AB5678
1 2 3 4 5 6 7 8 9 10 11 #include <stdio.h> unsigned replace_byte (unsigned x, int i, unsigned char b) { int move = i * 8 ; return x & ~(0xff << move) | b << move; } int main () { printf ("%.8x\n" , replace_byte(0x12345678 , 2 , 0xAB )); printf ("%.8x\n" , replace_byte(0x12345678 , 0 , 0xAB )); }
编译运行
输出
0x12AB5678
0x123456AB
2-61
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <stdio.h> int main () { int x; x = 0xffffff00 ; printf ("%d\n" , !~x); x = 0x000000ff ; printf ("%d\n" , !x); x = 0xffffff00 ; printf ("%d\n" , !~(x | ~0xff )); x = 0x00ffffff ; printf ("%d\n" ,!((x >> ((sizeof (int )-1 ) << 3 )) & 0xff )); }
编译运行
输出:
0
0
0
1
2-62
正数
源码,补码,反码
0
负数
源码
0
补码
左移补0
右移补1
反码
1
所以这里我们只需要判断(-1 >> 1) == -1
即可,因为-1
的补码为11
,右移一位后也是11
1 2 3 4 5 6 7 8 9 10 #include <stdio.h> int int_shift_are_arithmetic () { int test = -1 ; return (test >> 1 ) == -1 ; } int main () { int_shift_are_arithmetic(); }
编译运行
1 gcc 2_58.c && ./a.out ; echo $?
输出:
0
2-63
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <stdio.h> unsigned srl (unsigned x, int k) { unsigned xsra = (int ) x >> k; int w = sizeof (int ) * 8 ; unsigned z = 2 << (w - k - 1 ); return (z - 1 ) & xsra; } int sra (int x, int k) { int xsrl = (unsigned ) x >> k; int w = sizeof (int ) * 8 ; unsigned z = 1 << (w - k - 1 ); unsigned mask = z - 1 ; unsigned right = mask & xsrl; unsigned left = ~mask & (~(z & xsrl) + z); return left | right; } void test () { printf ("%x\n" , srl(8 , 2 )); printf ("%x\n" , sra(8 , 2 )); printf ("%x\n" , sra(-8 , 2 )); } int main () { test(); }
2-64
如果奇位都为1,则返会1,否则返回0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <stdio.h> int any_odd_one (unsigned x) { int mask = 0xAAAAAAAA ; return 0 != (x & mask); } int main () { int test1 = 0x5 ; int test2 = 0x7 ; printf ("%d\n" , any_odd_one(test1)); printf ("%d\n" , any_odd_one(test2)); }
编译运行
输出:
0
1