文章目录
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
);
printf("(float)ival:\n");
show_float(fval
);
printf("&ival:\n");
show_pointer(pval
);
}
其中变量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码值