Show Bytes-计算机学习日志

    xiaoxiao2023-11-12  142

    文章目录

    SHOW BYTES实验内容代码总览第一部分 int/float转unsigned char代码分析编译运行实验拓展 第二部分 取反后的机器数变化代码分析编译运行 第三部分 查看机器存储模式代码分析编译运行 第四部分 精度缺失代码分析编译运行 第五部分 字母字符转数字字符代码分析编译运行

    SHOW BYTES

    实验内容

    实现int/float向unsigned char*/char/unsigned int的转换查看机器数在机器里的存储方式(大端/小端模式)取反后机器数的变化模拟int转float时精度缺失的情况实现字母向数字的转换

    代码总览

    #include <stdio.h> #include <stdlib.h> #include <string.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("%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 *)); } void test_show_bytes(int val) { int ival = val; 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); } void simple_show_a() { int val = 0x87654321; byte_pointer valp = (byte_pointer) &val; show_bytes(valp, 1); show_bytes(valp, 2); show_bytes(valp, 3); } void simple_show_b() { int val = 0x12345678; byte_pointer valp = (byte_pointer) &val; show_bytes(valp, 1); show_bytes(valp, 2); show_bytes(valp, 3); } 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() { const char *s = "ABCDEF"; show_bytes((byte_pointer) s, strlen(s)); } void string_leg() { const char *s = "abcdef"; show_bytes((byte_pointer) s, strlen(s)); } void show_twocomp() { short x = 12345; short mx = -x; show_bytes((byte_pointer) &x, sizeof(short)); show_bytes((byte_pointer) &mx, sizeof(short)); } 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; }

    第一部分 int/float转unsigned char

    代码分析

    主函数中,当有传入参数时,进行如下操作: int val = 12345; if (argc > 1) { val = strtol(argv[1], NULL, 0);//将传入的数字字符串转长整型 printf("calling test_show_bytes\n"); test_show_bytes(val); } 主函数中调用函数test_show_bytes,目的为实现int/float向unsigned char*的转换。 void test_show_bytes(int val) { int ival = val; double fval = (double) ival; int *pval = &ival; printf("Stack variable ival = %d\n", ival);//堆栈变量 printf("(int)ival:\n"); show_int(ival);//实现int->unsigned char* printf("(float)ival:\n"); show_float(fval);//实现float->unsigned char* printf("&ival:\n"); show_pointer(pval);//输出ival存储地址 }

    其中变量fval定义为double而不是float,因为int转float时可能发生精度缺失,而double可以完整表示int,再由double转float时则不会发生以上现象。

    函数show_int和函数show_float分别实现int、float向unsigned char*的转换,函数show_pointer输出变量存储地址。 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 *)); } 函数show_bytes实现无符号数字字符及其地址的输出 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"); }

    编译运行

    操作指令 ./a.out 1073741824运行结果

    实验拓展

    若将typedef unsigned char *byte_pointer; 改为 typedef char *byte_pointer;

    运行结果

    若将typedef unsigned char *byte_pointer; 改为typedef int *byte_pointer;

    运行结果

    结果分析

    当定义指针类型为char时,假如机器数最高位为1,转换时则会补符号位,导致运行结果变化。当定义指针类型为int时,地址会加4。

    第二部分 取反后的机器数变化

    代码分析

    主函数中,未传入参数时,进行如下操作: 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(); } 主函数中调用函数show_twocomp,目的是实现short转化为unsigned char后,其机器数与其取反后的机器数的比较(机器数以十六进制表示)。 void show_twocomp() { short x = 12345; short mx = -x; show_bytes((byte_pointer) &x, sizeof(short)); show_bytes((byte_pointer) &mx, sizeof(short)); }

    编译运行

    操作指令 ./a.out运行结果

    第三部分 查看机器存储模式

    代码分析

    主函数中调用函数simple_show_a和simple_show_b,目的是查看不同系统中机器数的存储模式。 void simple_show_a() { int val = 0x87654321; byte_pointer valp = (byte_pointer) &val; show_bytes(valp, 1); //输出一个低地址端存储的机器数 show_bytes(valp, 2); //两个 show_bytes(valp, 3); //三个 } void simple_show_b() { int val = 0x12345678; byte_pointer valp = (byte_pointer) &val; show_bytes(valp, 1); show_bytes(valp, 2); show_bytes(valp, 3); }

    编译运行

    运行结果 Linux64位系统中采取小端模式存储

    第四部分 精度缺失

    代码分析

    主函数中调用函数float_eg,目的是为了模拟int强制转换为float后精度缺失的情况。 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); }

    编译运行

    运行结果 转载:《理解int转float为何会可能精度丢失的问题》link

    第五部分 字母字符转数字字符

    代码分析

    主函数中调用函数string_ueg和函数string_leg,目的是为了实现字母字符向数字字符的转换。 void string_ueg() { const char *s = "ABCDEF"; show_bytes((byte_pointer) s, strlen(s)); } void string_leg() { const char *s = "abcdef"; show_bytes((byte_pointer) s, strlen(s)); }

    编译运行

    运行结果 转换过程依据字母的ASCLL码值
    最新回复(0)