计算机系统基础日志No.4 show bytes-打印数据的字节表示形式
文章目录
一,原程序及编译运行1.源程序2.编译运行
二,程序拓展1.把byte_pointer改为int *1>程序结果2>int*结果分析
2.把byte_pointer改为char *1>程序结果2>char*结果分析
一,原程序及编译运行
1.源程序
/* show-bytes - prints byte representation of data */
/* $begin show-bytes */
#include <stdio.h>
/* $end show-bytes */
#include <stdlib.h>
#include <string.h>
/* $begin show-bytes */
typedef unsigned char *byte_pointer;
//typedef char *byte_pointer;
//typedef int *byte_pointer;
void show_bytes(byte_pointer start, size_t len) {
size_t i;
for (i = 0; i < len; i++)
printf("%p\t0x%.2x\n", &start[i], start[i]);
printf("\n");
}
void show_int(int x) {
show_bytes((byte_pointer) &x, sizeof(int));
}
void show_float(float x) {
show_bytes((byte_pointer) &x, sizeof(float));
}
void show_pointer(void *x) {
show_bytes((byte_pointer) &x, sizeof(void *));
}
/* $end show-bytes */
/* $begin test-show-bytes */
void test_show_bytes(int val) {
int ival = val;
//float fval = (float) ival;
double fval = (double) ival;
int *pval = &ival;
printf("Stack variable ival = %d\n", ival);
printf("(int)ival:\n");
show_int(ival);
printf("(float)ival:\n");
show_float(fval);
printf("&ival:\n");
show_pointer(pval);
}
/* $end test-show-bytes */
void simple_show_a() {
/* $begin simple-show-a */
int val = 0x87654321;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */
/* $end simple-show-a */
}
void simple_show_b() {
/* $begin simple-show-b */
int val = 0x12345678;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */
/* $end simple-show-b */
}
void float_eg() {
int x = 3490593;
float f = (float) x;
printf("For x = %d\n", x);
show_int(x);
show_float(f);
x = 3510593;
f = (float) x;
printf("For x = %d\n", x);
show_int(x);
show_float(f);
}
void string_ueg() {
/* $begin show-ustring */
const char *s = "ABCDEF";
show_bytes((byte_pointer) s, strlen(s));
/* $end show-ustring */
}
void string_leg() {
/* $begin show-lstring */
const char *s = "abcdef";
show_bytes((byte_pointer) s, strlen(s));
/* $end show-lstring */
}
void show_twocomp()
{
/* $begin show-twocomp */
short x = 12345;
short mx = -x;
show_bytes((byte_pointer) &x, sizeof(short));
show_bytes((byte_pointer) &mx, sizeof(short));
/* $end show-twocomp */
}
int main(int argc, char *argv[])
{
int val = 12345;
if (argc > 1) {
val = strtol(argv[1], NULL, 0);
printf("calling test_show_bytes\n");
test_show_bytes(val);
} else {
printf("calling show_twocomp\n");
show_twocomp();
printf("Calling simple_show_a\n");
simple_show_a();
printf("Calling simple_show_b\n");
simple_show_b();
printf("Calling float_eg\n");
float_eg();
printf("Calling string_ueg\n");
string_ueg();
printf("Calling string_leg\n");
string_leg();
}
return 0;
}
2.编译运行
calling show_twocomp
0x7fffc3b39ee4 0x39
0x7fffc3b39ee5 0x30
0x7fffc3b39ee6 0xc7
0x7fffc3b39ee7 0xcf
Calling simple_show_a
0x7fffc3b39edc 0x21
0x7fffc3b39edc 0x21
0x7fffc3b39edd 0x43
0x7fffc3b39edc 0x21
0x7fffc3b39edd 0x43
0x7fffc3b39ede 0x65
Calling simple_show_b
0x7fffc3b39edc 0x78
0x7fffc3b39edc 0x78
0x7fffc3b39edd 0x56
0x7fffc3b39edc 0x78
0x7fffc3b39edd 0x56
0x7fffc3b39ede 0x34
Calling float_eg
For x = 3490593
0x7fffc3b39ebc 0x21
0x7fffc3b39ebd 0x43
0x7fffc3b39ebe 0x35
0x7fffc3b39ebf 0x00
0x7fffc3b39ebc 0x84
0x7fffc3b39ebd 0x0c
0x7fffc3b39ebe 0x55
0x7fffc3b39ebf 0x4a
For x = 3510593
0x7fffc3b39ebc 0x41
0x7fffc3b39ebd 0x91
0x7fffc3b39ebe 0x35
0x7fffc3b39ebf 0x00
0x7fffc3b39ebc 0x04
0x7fffc3b39ebd 0x45
0x7fffc3b39ebe 0x56
0x7fffc3b39ebf 0x4a
Calling string_ueg
0x5557af22ad34 0x41
0x5557af22ad35 0x42
0x5557af22ad36 0x43
0x5557af22ad37 0x44
0x5557af22ad38 0x45
0x5557af22ad39 0x46
Calling string_leg
0x5557af22ad3b 0x61
0x5557af22ad3c 0x62
0x5557af22ad3d 0x63
0x5557af22ad3e 0x64
0x5557af22ad3f 0x65
0x5557af22ad40 0x66
二,程序拓展
1.把byte_pointer改为int *
1>程序结果
calling show_twocomp
0x7ffe0e250ef4 0xcfc73039
0x7ffe0e250ef8 0x1549db00
0x7ffe0e250ef6 0xdb00cfc7
0x7ffe0e250efa 0xda411549
Calling simple_show_a
0x7ffe0e250eec 0x87654321
0x7ffe0e250eec 0x87654321
0x7ffe0e250ef0 0xe250eec
0x7ffe0e250eec 0x87654321
0x7ffe0e250ef0 0xe250eec
0x7ffe0e250ef4 0x7ffe
Calling simple_show_b
0x7ffe0e250eec 0x12345678
0x7ffe0e250eec 0x12345678
0x7ffe0e250ef0 0xe250eec
0x7ffe0e250eec 0x12345678
0x7ffe0e250ef0 0xe250eec
0x7ffe0e250ef4 0x7ffe
Calling float_eg
For x = 3490593
0x7ffe0e250ecc 0x354321
0x7ffe0e250ed0 0xe250f00
0x7ffe0e250ed4 0x7ffe
0x7ffe0e250ed8 0xbbe37a6c
0x7ffe0e250ecc 0x4a550c84
0x7ffe0e250ed0 0xe250f00
0x7ffe0e250ed4 0x7ffe
0x7ffe0e250ed8 0xbbe37a7c
For x = 3510593
0x7ffe0e250ecc 0x359141
0x7ffe0e250ed0 0xe250f00
0x7ffe0e250ed4 0x7ffe
0x7ffe0e250ed8 0xbbe37aad
0x7ffe0e250ecc 0x4a564504
0x7ffe0e250ed0 0xe250f00
0x7ffe0e250ed4 0x7ffe
0x7ffe0e250ed8 0xbbe37abd
Calling string_ueg
0x5602bbe37d44 0x44434241
0x5602bbe37d48 0x61004645
0x5602bbe37d4c 0x65646362
0x5602bbe37d50 0x61630066
0x5602bbe37d54 0x6e696c6c
0x5602bbe37d58 0x65742067
Calling string_leg
0x5602bbe37d4b 0x64636261
0x5602bbe37d4f 0x63006665
0x5602bbe37d53 0x696c6c61
0x5602bbe37d57 0x7420676e
0x5602bbe37d5b 0x5f747365
0x5602bbe37d5f 0x776f6873
2>int*结果分析
为什么会是这个呢? 通过debug,发现 printf("%.2x", start[i]); start[i]被解释为了int。所以,程序每次读取4个字节(int 的大小),并以16进制输出。 可以通过内存值来证明 start[0] 39 30 00 00 -> 3039 start[1] 5a 10 3a 01 -> 013a 105a start[2] 5a 10 3a 01 -> 013a 105a start[3] 00 90 f0 00 -> 00f0 0900 这也和输出是符合的。
2.把byte_pointer改为char *
1>程序结果
calling show_twocomp
0x7ffdc1d86654 0x39
0x7ffdc1d86655 0x30
0x7ffdc1d86656 0xffffffc7
0x7ffdc1d86657 0xffffffcf
Calling simple_show_a
0x7ffdc1d8664c 0x21
0x7ffdc1d8664c 0x21
0x7ffdc1d8664d 0x43
0x7ffdc1d8664c 0x21
0x7ffdc1d8664d 0x43
0x7ffdc1d8664e 0x65
Calling simple_show_b
0x7ffdc1d8664c 0x78
0x7ffdc1d8664c 0x78
0x7ffdc1d8664d 0x56
0x7ffdc1d8664c 0x78
0x7ffdc1d8664d 0x56
0x7ffdc1d8664e 0x34
Calling float_eg
For x = 3490593
0x7ffdc1d8662c 0x21
0x7ffdc1d8662d 0x43
0x7ffdc1d8662e 0x35
0x7ffdc1d8662f 0x00
0x7ffdc1d8662c 0xffffff84
0x7ffdc1d8662d 0x0c
0x7ffdc1d8662e 0x55
0x7ffdc1d8662f 0x4a
For x = 3510593
0x7ffdc1d8662c 0x41
0x7ffdc1d8662d 0xffffff91
0x7ffdc1d8662e 0x35
0x7ffdc1d8662f 0x00
0x7ffdc1d8662c 0x04
0x7ffdc1d8662d 0x45
0x7ffdc1d8662e 0x56
0x7ffdc1d8662f 0x4a
Calling string_ueg
0x55bb9bfdbd34 0x41
0x55bb9bfdbd35 0x42
0x55bb9bfdbd36 0x43
0x55bb9bfdbd37 0x44
0x55bb9bfdbd38 0x45
0x55bb9bfdbd39 0x46
Calling string_leg
0x55bb9bfdbd3b 0x61
0x55bb9bfdbd3c 0x62
0x55bb9bfdbd3d 0x63
0x55bb9bfdbd3e 0x64
0x55bb9bfdbd3f 0x65
0x55bb9bfdbd40 0x66
2>char*结果分析
再次debug此时start[i]被解释为了char test =12345的16进制为00003039。 test=54321的16进制为0000d431 而问题就是出现在这。 在打印test的情况下, start[0] 39 <128 start[1] 30 <128 start[2] 00 <128 start[3] 00 <128 都是在char的正常范围。但是在打印test=54321的情况下 start[0] 31 <128 start[1] d4 >128 start[2] 00 <128 start[3] 00 <127 在打印start[1]时,值超过了char的正常范围。本来也是没什么问题的,但是此时打印格式是16进制。所以程序按照补码扩充。 d4 -> 1101 0111 -> 1111 1111 1111 1111 1111 1111 1101 0111->F F F F F F D 4 所以出了错误