(下面是cmu的代码)
/* 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;//用byte_pointer来表示unsigned char*类型 //typedef char *byte_pointer; //typedef int *byte_pointer; void show_bytes(byte_pointer start, size_t len) {//size_t是标准C库中定义的,应为unsigned int,在64位系统中为 long unsigned int。 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));//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_fer 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);//将参数nptr字符串根据参数base来转换成长整型数 printf("calling test_show_bytes\n"); test_show_bytes(val); } else { //不带参数时的运行结果,其实都是调用show_byte函数,只不过参数一个内定,一个自己输入 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; }这个函数输出一个数值在内存中是怎么表示的。通过此函数,我们可以知道自己的电脑存储时是按大端法排列还是小端法排列(小端法排列是低地址对地位,高地址对高位,大端法则反之)。
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 */ } /*以下为输出案例,从这我们可以看出低位的78对应低地址0xbfa18b48,所以我们的电脑是使用小端法进行存储的。 Calling simple_show_b 0xbfa18b48 0x78 0xbfa18b48 0x78 0xbfa18b49 0x56 0xbfa18b48 0x78 0xbfa18b49 0x56 0xbfa18b4a 0x34*/在代码的第9~11行:
typedef unsigned char *byte_pointer;//用byte_pointer来表示unsigned char*类型 //typedef char *byte_pointer; //typedef int *byte_pointer;我们需要思考一个问题,为什么要用unsigned char *表示byte_pointer,而不用char *或者int*来表示。
我们来看看同一个函数,如果用不同的byte_pointer来表示会怎么样:
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_fer valp = (byte_pointer) &val; show_bytes(valp, 1); /* A. */ show_bytes(valp, 2); /* B. */ show_bytes(valp, 3); /* C. */ /* $end simple-show-a */ } /*typedef unsigned char *byte_pointer的结果 (float)ival: 0xbfd40020 0x00 0xbfd40021 0x00 0xbfd40022 0x80 0xbfd40023 0x4e 改为:typedef char *byte_pointer的结果 (float)ival: 0xbfbe3150 0x00 0xbfbe3151 0x00 0xbfbe3152 0xffffff80 0xbfbe3153 0x4e 改为:typedef int *byte_pointer的结果 (float)ival: 0x7ffd0d703e0c 0x4e800000 0x7ffd0d703e10 0xd703e50 0x7ffd0d703e14 0x7ffd 0x7ffd0d703e18 0x73fe8924*/改为:typedef int *byte_pointer的结果:start[i]被解释为int,一次读取四个字节,所以第一个输出是对的,后面输出的是越界了的,是别人的量了。
改为:typedef char *byte_pointer的结果:start[i]被解释为char,一次读取一个字节。 可以看到0xbfbe3152 0xffffff80这里出问题了。ox80超过了char的最大表示正范围ox7f,此时打印格式是16进制。所以程序按照补码扩充。所以前面全是1111即f。所以变成无符号的char*类型 也是为了减少发生这种现象,让自己的正范围变大。
最后,感谢这位博主关于为什么使用unsigned char *的答案:https://blog.csdn.net/weixin_41256413/article/details/79897033