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 ...
随机推荐
- Fundebug前端JavaScript插件更新至1.8.2,修复2个小BUG
摘要: 修复2个BUG,请大家及时更新. Fundebug前端异常监控服务 Fundebug是专业的程序异常监控平台,我们JavaScript插件可以提供全方位的异常监控,可以帮助开发者第一时间定位各 ...
- scikit-learn 中的 KMeans
语法 sklearn.cluster.KMeans(n_clusters=8, # 簇的个数, 默认为 8 init='k-means++', # 初始簇中心的获取方法 n_init=10, # 初始 ...
- Latex 调整断字,连接符,取消断词/断字
latex使用了处理断字的算法去自动的找断字的地方,而且latex会调整单词间距,使得文章看起来不会显得疏密不一致.大多数情况下,这些算法都工作得很好.但是因为断字的算法是根据某种规则来处理单词的断字 ...
- 01-Eigen的安装
Ubuntu下: 使用的IDE是Kdevelop.(使用别的也可以) 安装Kdevelop的方法见: http://www.cnblogs.com/alexYuin/p/8989228.html 1. ...
- limits the number of elements in an IN predicate to 2100 entries.
org.hibernate.engine.jdbc.spi.SqlExceptionHelper 131 - [TxId : f68db5f5b-qmgnc^1561639897640^271530 ...
- First Chance Exception是什么?
是否调试过应用程序并在输出窗口中看到有关“First Chance”异常的消息?有没有想过: 什么是First Chance Exception? 第一次机会异常是否意味着我的代码中存在问题? 在调试 ...
- webpack中路径的理解
webpack 前端打包工具, 开发人员要面对的路径主要是: 打包前的路径(开发环境路径)和打包后的路径(生产环境路径) 在webpack.config.js中配置的output.path, outp ...
- django运行报错TypeError: object supporting the buffer API required
运行django项目报错:TypeError: object supporting the buffer API required 解决方案: 将settings.py中数据库的密码改成字符串格式 源 ...
- ABP .net framework版 的发布
先正常的发布流程走 特别的如下图
- C++标准库中的std::endl究竟做了什么?
先抓出std::endl的源代码: /** * @file ostream * @brief Write a newline and flush the stream. * * This m ...