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_pointerunsigned char*,而我的是char*
这有什么问题呢,charunsigned char都是一个字节,八位二进制,两位十六进制,为什么会发生多输出三个字节的情况呢。
通过查阅,我发现问题正出在charunsigned char中:c语言中 char* 和 unsigned char* 的区别浅析
具体原因是这样的:
C语言中虽然没有具体说明char有无符号,但是大多数机器上char都是有符号的,而printf中格式输出%.2x的过程为:先把char类型转换为int类型,然后再把int类型转换为二进制。这就涉及到了位的扩展,而有符号数的位扩展所遵循的是--‘符号扩展’具体见我的新博客~。
所以在扩展时,如果char类型的位模式中第一位是1的话,扩展为int类型,需要在前面加三个字节24位的1,printf时实际精度超过了.2x,自然就在这个字节的前面加了六个f。

CSAPP第二章show_bytes函数的探究的更多相关文章

  1. 第二章----python函数

    第一节:调用函数 1.函数是什么? 函数是组织好的,可以重复利用的. 2.为什么要用到函数? 提高应用的模块性,提高重复利用率.指的是:多个文件中可能都要用到该函数,直接拿来调用就行,不用在重复写一个 ...

  2. 第二章 Js函数

      函数的定义二种定义 ①function myfunc () { console("hello"); }; ②var myfunc = function () { console ...

  3. SQL Server(第二章) 字符串函数、日期时间函数、转换函数

    --1.CONCAT 函数:字符串连接(支持sql server2012 SQL规则 如果与NULL连接返回NILL) SELECT empid,CONCAT(firstname,lastname) ...

  4. 第二章JavaScript 函数和对象

    1 JavaScript 函数 1.1 声明函数的方式 function 关键字 匿名函数方式(表达式方式) Function 构造函数方式 1.2 参数问题 形参和实参数量问题 可选形参(参数默认值 ...

  5. CSAPP 第二章随笔

    类型转换问题 (1)int -> short 二进制位高位截断,低位保持不变 (2)同类型 unsign -> sign 记住二进制位是不变的 (3)P101页提到的编译器乘法优化问题,一 ...

  6. Python自学:第二章 使用函数str( )避免类型错误

    age = 23 message = "Happy " + str(age) + "rd Birthday" print(message) 输出位 Happy ...

  7. 读CSAPP第二章的收获

    一:一道很有意思的位运算题目:你只有两种操作 bis(x, y): 在y为1的每个位置上,将x的对应的位设为1bic(x, y): 在y为1的每个位置上,将x的对应的位设为0 简单的化简一下bis(x ...

  8. Python 对象(type/object/class) 作用域 一等函数 (慕课--Python高级,IO并发 第二章)

    在python中一共有两种作用域:全局作用域和函数作用域全局作用域:在全局都有效,全局作用域在程序执行时创建,在程序执行结束时销毁:所有函数以外的区域都是全局作用域:在全局作用域中定义的变量,都属于全 ...

  9. [书籍翻译] 《JavaScript并发编程》 第二章 JavaScript运行模型

    本文是我翻译<JavaScript Concurrency>书籍的第二章 JavaScript运行模型,该书主要以Promises.Generator.Web workers等技术来讲解J ...

随机推荐

  1. elasticsearch查询篇索引映射文档数据准备

    elasticsearch查询篇索引映射文档数据准备 我们后面要讲elasticsearch查询,先来准备下索引,映射以及文档: 我们先用Head插件建立索引film,然后建立映射 POST http ...

  2. OpenInstall实现APP无邀请码推广

    1.登录OpenInstall网站,这里会为你创建一个AppKey,而这个东西在web页面会用到. 2.在推广页面中加入推广下载. <script type="text/javascr ...

  3. linux 利器

    ncat nc strace dmesg    很重要,好多错误从程序的角度无法得到答案

  4. 使用apache.tika判断文件类型

    一. 判断文件类型一般可采用两种方式 1. 后缀名判断 简单易操作,但无法准确判断类型 2. 文件头信息判断 通常可以判断文件类型,但有些文件类型无法判断(如word和excel头信息的前几个字节是一 ...

  5. system.exit(int status)中status值不同时的区别

    status为0时为正常退出程序,也就是结束当前正在运行中的java虚拟机. status为非0的其他整数(包括负数,一般是1或者-1),表示非正常退出当前程序. 可以明确的是,无论status是什么 ...

  6. 洛谷p2827蚯蚓题解

    题目 算法标签里的算法什么的都不会啊 什么二叉堆?? qbxt出去学习的时候讲的,一段时间之前做的,现在才写到博客上的 维护3个队列,队列1表示最开始的蚯蚓,队列2表示每一次被切的蚯蚓被分开的较长的那 ...

  7. Java代理(静态代理、JDK动态代理、CGLIB动态代理)

    Java中代理有静态代理和动态代理.静态代理的代理关系在编译时就确定了,而动态代理的代理关系是在运行期确定的.静态代理实现简单,适合于代理类较少且确定的情况,而动态代理则给我们提供了更大的灵活性. J ...

  8. Mac-搭建Hadoop集群

    You have to work very hard to believe that you are really powerless. Mac-搭建Hadoop集群 我用到了:VMware Fusi ...

  9. python 项目实战之备份文件夹并且压缩文件夹及下面的文件

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019/11/12 14:21 # @Author : zoulixiang # @S ...

  10. es6引用模块import后面加上花括号{}和不加花括号的区别

    在使用import语法引用模块时,如何正确使用{} 例如:有两个文件,home.js.user.js 当需要在home.js中引入user.js的时候 //home.js import user fr ...