CSAPP第二章show_bytes函数的探究
CSAPP第二章中给出了一个帮助我们观察数据的位模式的函数--show_bytes函数,具体实现如下:
#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_double(double x)
{
show_bytes((byte_pointer)&x, sizeof(double));
}
void show_float(float x)
{
show_bytes((byte_pointer)&x, sizeof(float));
}
函数是不难懂的,只要有C语言基础的应该都能看懂,所以在看懂函数后,我第一时间想自己实现一下,实现代码如下:
#include<stdio.h>
typedef char *byte_pointer;
void show_bytes(byte_pointer start, size_t len)
{
for (int 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_double(double x)
{
show_bytes((byte_pointer)&x, sizeof(double));
}
void show_float(float x)
{
show_bytes((byte_pointer)&x, sizeof(float));
}
写完后我立刻尝试跑了一下一个int类型的数字
int main(void)
{
int x=1;
show_int(x);
}
VS2017运行结果为:

看上去是没什么问题的。于是我又试了一下浮点数的表示:
int main(void)
{
float x = 1.0f;
show_float(x);
}
VS2017运行结果为:

输出了14个十六进制数字,多输出了6个十六进制数,即3个字节。
这三个字节是怎么来的呢?
通过对比发现我写的函数与书中的函数一个不同,书中的byte_pointer是unsigned char*,而我的是char*。
这有什么问题呢,char与unsigned char都是一个字节,八位二进制,两位十六进制,为什么会发生多输出三个字节的情况呢。
通过查阅,我发现问题正出在char与unsigned char中:c语言中 char* 和 unsigned char* 的区别浅析。
具体原因是这样的:
C语言中虽然没有具体说明char有无符号,但是大多数机器上char都是有符号的,而printf中格式输出%.2x的过程为:先把char类型转换为int类型,然后再把int类型转换为二进制。这就涉及到了位的扩展,而有符号数的位扩展所遵循的是--‘符号扩展’具体见我的新博客~。
所以在扩展时,如果char类型的位模式中第一位是1的话,扩展为int类型,需要在前面加三个字节24位的1,printf时实际精度超过了.2x,自然就在这个字节的前面加了六个f。
CSAPP第二章show_bytes函数的探究的更多相关文章
- 第二章----python函数
第一节:调用函数 1.函数是什么? 函数是组织好的,可以重复利用的. 2.为什么要用到函数? 提高应用的模块性,提高重复利用率.指的是:多个文件中可能都要用到该函数,直接拿来调用就行,不用在重复写一个 ...
- 第二章 Js函数
函数的定义二种定义 ①function myfunc () { console("hello"); }; ②var myfunc = function () { console ...
- SQL Server(第二章) 字符串函数、日期时间函数、转换函数
--1.CONCAT 函数:字符串连接(支持sql server2012 SQL规则 如果与NULL连接返回NILL) SELECT empid,CONCAT(firstname,lastname) ...
- 第二章JavaScript 函数和对象
1 JavaScript 函数 1.1 声明函数的方式 function 关键字 匿名函数方式(表达式方式) Function 构造函数方式 1.2 参数问题 形参和实参数量问题 可选形参(参数默认值 ...
- CSAPP 第二章随笔
类型转换问题 (1)int -> short 二进制位高位截断,低位保持不变 (2)同类型 unsign -> sign 记住二进制位是不变的 (3)P101页提到的编译器乘法优化问题,一 ...
- Python自学:第二章 使用函数str( )避免类型错误
age = 23 message = "Happy " + str(age) + "rd Birthday" print(message) 输出位 Happy ...
- 读CSAPP第二章的收获
一:一道很有意思的位运算题目:你只有两种操作 bis(x, y): 在y为1的每个位置上,将x的对应的位设为1bic(x, y): 在y为1的每个位置上,将x的对应的位设为0 简单的化简一下bis(x ...
- Python 对象(type/object/class) 作用域 一等函数 (慕课--Python高级,IO并发 第二章)
在python中一共有两种作用域:全局作用域和函数作用域全局作用域:在全局都有效,全局作用域在程序执行时创建,在程序执行结束时销毁:所有函数以外的区域都是全局作用域:在全局作用域中定义的变量,都属于全 ...
- [书籍翻译] 《JavaScript并发编程》 第二章 JavaScript运行模型
本文是我翻译<JavaScript Concurrency>书籍的第二章 JavaScript运行模型,该书主要以Promises.Generator.Web workers等技术来讲解J ...
随机推荐
- MYSQL入门操作和常规DML、DDL、DQL使用
刷新权限,将某些权限从硬盘刷新到内存中(修改root密码自带隐式刷新权限操作) mysql> flush privileges; Query OK, 0 rows affected (0.00 ...
- JS数据打印的几种方式
/** * 在页面输出内容! */ document.write("This's Great!"); /** * 控制台打印: */ console.log("This ...
- mysql 忘记密码,赋予用户权限,两台服务器的数据库之间快速导入
mysql 忘记密码: 1.首先service mysql stop mysqld --skip-grant-tables & 开启数据库 然后就可以mysql -uroot 直接进数据库, ...
- python常用库(转)
转自http://www.west999.com/info/html/wangluobiancheng/qita/20180729/4410114.html Python常用的库简单介绍一下 fuzz ...
- Linux服务器安全加固
关于对公司网站服务器安全加固的一些想法及思路: 一.修改密码和ssh登录端口,并且尽可能的用密钥对登录,禁止用密码登录(主要针对Linux)二.修改/etc/hosts.allow 设置仅仅允许某几台 ...
- 【目录】Jmeter系列
为天地立心,为生民立命.为往圣继绝学,为万世开太平. ---<横渠四句>·张载 Jmeter(一)简介以及环境搭建 Jmeter(二)Jmeter目录介绍 Jmeter(三)Test-Pl ...
- Fluter基础巩固之Dart语言详解<一>
在上一篇https://www.cnblogs.com/webor2006/p/11367345.html中咱们已经搭建好了Flutter的开发环境了,而Flutter的开发语言是选用的dart,那么 ...
- HDU3507:Print Article(斜率优化dp)
传送门 题意: 现有\(n\)个数,每个数的值为\(a_i\),现在可以把数划分为多段,每一段的代价为\((\sum_{k=i}^{j}c_i)^2+M\). 问怎么划分,代价最小. 思路: 考虑dp ...
- idea下新建Spring Boot项目并配置启动
一.操作步骤 ①使用idea新建一个Spring Boot项目 ②修改pom.xml ③修改application.properties ④修改编写一个Hello Spring Boot的Contro ...
- .Net Core 获取项目所有程序集,排除Microsoft、Nuget下载的
https://www.cnblogs.com/yanglang/p/6866165.html public static List<Assembly> BaiqianAssemblies ...