当前位置: 首页 > 编程日记 > 正文

《深入理解计算机系统》学习心得二:关于show-bytes的 学习

此段代码,使用强制类型转换来访问和打印不同程序对象的字节表示。show-bytes打印出每个以十六进制表示的字节。

/* show-bytes - prints byte representation of data */
/* $begin show-bytes */
#include <stdio.h>
/* $end show-bytes */
#include <stdlib.h>
#include <string.h>
/* $begin show-bytes */typedef unsigned char *byte_pointer;
//typedef char *byte_pointer;
//typedef int *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 *));
}
/* $end show-bytes */

 代码说明

#include <stdio.h>

在程序中用到系统提供的标准函数库中的输入输出函数时,应在程序的开头写上一行:#include"stdio.h"或者是#include<stdio.h>,这样才能调用库函数。二者主要在于查找效率上有差别,#include<stdio.h>一般用包含系统文件,它是查找先从系统目录查找开始查找;#include "stdio.h"一般用包含项目文件,它是查找先从项目目录查找开始查找。

在编写C语言中,常用到printf()和scanf()函数,他们就是stdio.h中的两个标准输入输出函数,所以编程语句中如果要用到此两个函数就一定要在头文件中加入#include<stdio.h>。

#include <stdlib.h>

stdlib 头文件即standard library标准库头文件。stdlib.h里面定义了五种类型、一些宏和通用工具函数。 类型例如size_t、wchar_t、div_t、ldiv_t和lldiv_t; 宏例如EXIT_FAILURE、EXIT_SUCCESS、RAND_MAX和MB_CUR_MAX等等; 常用的函数如malloc()、calloc()、realloc()、free()、system()、atoi()、atol()、rand()、srand()、exit()等等。 具体的内容可以打开编译器的include目录里面的stdlib.h头文件查看。

#include <string.h>

使用字符串的函数的时候需要添加此头文件。比如如下常用函数:
strlen求字符串长度
strcmp比较2个字符串是否一样
strcat字符串连接操作
strcpy字符串拷贝操作
strncat字符串连接操作(前n个字符)
strncpy字符串拷贝操作(前n个字符)
strchr 查询子串
strstr 查询字串

typedef unsigned char *byte_pointer;

我们用typedef将数据类型byte_pointer定义为一个指向类型为“unsigned char”的对象的指针。这样一个字节指针引用一个字节序列,其中每个字节都会被认为是一个非负整数。

void show_bytes(byte_pointer start, size_t len)

这个函数有一个类型为byte_pointer的参数start。在c语言中,我们能够用数组表示法来引用指针,同时我们也能用指针表示法来引用数组参数。在这个例子中,引用start[i]表示我们想要读取以start指向的位置为起始的第i个位置处的字节。

第一个例程show-bytes的输入是一个字节序列的地址,它用一个字节指针以及一个字节数来指示。该字节数指定为数据类型size_t,表示数据结构大小的首选数据类型。

printf("%p\t0x%.2x\n", &start[i], start[i]);

C格式化指令“%.2x”表明整数必须用至少两个数字的十六进制输出。 在格式串里,每个以“%”开始的字符序列都表示如何格式化下一个参数。 “%p”表示指针输出。“%d”表示输出一个十进制整数。“%f”是输出一个浮点数。“%c”是输出一个字符,其编码由参数给出。

Tab是制表符,就是"\t",作用是预留8个字符的显示宽度,用于对齐

详情请见:c语言printf()输出格式大全(转载)

printf("\n");

在c语言中,换行(\n)就是光标下移一行却不会移到这一行的开头,回车(\r)就是回到当前行的开头却不向下移一行.
Enter键按下后会执行\n\r这样就是我们看到的一般意义的回车了,所以你用16进制文件查看方式看一个文本,就会在行尾发现"\n\r"

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-int 、show-float和show_pointer展示了如何使用程序show_bytes来分别输出类型为int、float和void *的c程序对象的字节表示。可以观察到他们仅仅传递给show_bytes一个指向它们参数x的指针&x,且这个指针被强制转化为“unsigned char *”。这种强制类型转换告诉编译器,程序应该把这个指针看成指向一个字节序列,而不是指向一个原始数据类型的对象。然后,这个指针会被看成是对象使用的最低字节地址。强制转换类型运算符可以将一种数据类型转换成另一种。因此,强制类型转换(byte_pointer)&x表示无论指针&x以前是什么类型,他现在就是一个指向数据类型为unsigned char 的指针。

这些过程使用c语言的运算符sizeof来确定对象使用的字节数。一般来说,表达式sizeof(T)返回存储一个类型为T的对象所需要的字节数。使用sizeof而不是一个固定的值,是向编写在不同机器类型上可移植的代码迈进了一步。

一、C语言变量名的命名规则:(可以字母,数字,下划线混合使用) 
1. 只能以字母或下划线开始; 
2. 不能以数字开始; 
3. 一般小写; 
4. 关键字不允许用(eg:int float=2//error  float 为保留字不允许用);

二、函数名的命名规则 
1.见名知意; 
2.自定义函数函数名首字母大写(库函数里的函数名都是以小写字母定义,为了区分库函数和自定义函数,避免冲突)。

三、宏定义里面的变量 全大写 
eg: 
#define SIZE 100(后面函数所有出现的SIZE全用100代替,它在所有函数执行前先执行)

原文:变量函数命名规则(转载)

/* $begin test-show-bytes */
void test_show_bytes(int val) {int ival = val;//float fval = (float) ival;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);
}
/* $end test-show-bytes */

以上为打印输出:测试显示字节

void simple_show_a() {
/* $begin simple-show-a */
int val = 0x87654321;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */
/* $end simple-show-a */

在小端法机器上,它将按照从最低有效字节到最高有效字节的顺序列出字节(低对低,高对高);在大端法机器上,他将按照从最高有效字节到最低有效字节的顺序列出字节。

void simple_show_b() {
/* $begin simple-show-b */
int val = 0x12345678;
byte_pointer valp = (byte_pointer) &val;
show_bytes(valp, 1); /* A. */
show_bytes(valp, 2); /* B. */
show_bytes(valp, 3); /* C. */
/* $end simple-show-b */
}
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() {
/* $begin show-ustring */
const char *s = "ABCDEF";
show_bytes((byte_pointer) s, strlen(s)); 
/* $end show-ustring */
}
void string_leg() {
/* $begin show-lstring */
const char *s = "abcdef";
show_bytes((byte_pointer) s, strlen(s)); 
/* $end show-lstring */
}
void show_twocomp() 
{
/* $begin show-twocomp */short x = 12345; short mx = -x; show_bytes((byte_pointer) &x, sizeof(short)); show_bytes((byte_pointer) &mx, sizeof(short)); 
/* $end show-twocomp */
}
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;
}

typedef unsigned char *byte_pointer运行结果

不带参数的运行结果:./bytes 
unsigned char不带参数的运行结果:./bytes
不带参数的运行结果
unsigned char不带参数的运行结果:./bytes

./bytes 65535
unsigned char带一个参数的运行结果   ./bytes 65535
带一个参数的运行结果  ./bytes 3.14
unsigned char带一个参数的运行结果  ./bytes 3.14
带一个参数的运行结果 ./bytes -32768
unsigned char带一个参数的运行结果 ./bytes -32768

char 不带参数的运行结果 ./bytes
char 不带参数的运行结果 ./bytes
char 不带参数的运行结果 ./bytes
char 不带参数的运行结果 ./bytes
带一个参数的运行结果 ./bytes 65535
char带一个参数的运行结果 ./bytes 65535

typedef int *byte_pointer的运行结果

int 不带参数的运行结果 ./bytes
int 不带参数的运行结果 ./bytes
int 不带参数的运行结果 ./bytes
int 不带参数的运行结果 ./bytes
int 带一个参数的运行结果 ./bytes 65535
int 带一个参数的运行结果 ./bytes 65535

解答为何要以unsigned char作为类型:

通过对测试结果进行分析,当定义指针为int型时,地址会加4;当定义指针类型为有符号的char型时, 假如遇到最高位为1时,则会出现补符号位置的形式。

相关文章:

Jquery基础:append、prepend、after、before、appendTo的区别

append() 是在被选元素的结束标签前面(即改被选元素的内部)插入指定内容。 <html><head><script type"text/javascript" src"/jquery/jquery.js"></script><script type"text/javascript">      $().ready(…

域名删除时间及whois状态说明

国际域名状态 Active : 正常状态&#xff1b; Registry-hold&#xff1a;注册局暂停&#xff0c;域名没有解析&#xff0c;不能正常使用&#xff0c;可以续费&#xff1b; Registry-lock&#xff1a;注册局锁定&#xff0c;域名有解析&#xff0c;正常使用&#xff0c;不能更改…

JavaScript中的正则表达式解析

正则表达式(regular expression)对象包含一个正则表达式模式(pattern)。它具有用正则表达式模式去匹配或代替一个字符串(string)中特定字符(或字符集合)的属性(properties)和方法(methods)。 要为一个单独的正则表达式添加属性,可以使用正则表达式构造函数(constructor functio…

Markdown上下标内容多于一项

用{ }括起来。转载于:https://www.cnblogs.com/144823836yj/p/10261391.html

详述FileUpload 控件上传单文件

第一步&#xff1a;添加两个Label控件&#xff0c;一个是用于标题显示&#xff0c;一个是用于上传完成消息提示。 第二步&#xff1a;创建一个FileUpload控件到Page页面&#xff0c;注意FileUpload控件本身只提供文件的选举操作&#xff0c;而实际的文件上传功能需要我们创建一…

基于μC/OS—III的CC1120驱动程序设计

基于μC&#xff0f;OS—III的CC1120驱动程序设计 时间&#xff1a;2014-01-21 来源&#xff1a;电子设计工程 作者&#xff1a;张绍游&#xff0c;张贻雄&#xff0c;石江宏关键字&#xff1a;CC1120 嵌入式操作系统 STM32F103ZE 驱动设计 摘要&#xff1a;本文根据实…

LinkQueue的基本创建

队列是一种先进先出&#xff08;first in first out,缩写为FIFO&#xff09;的线性表。它只允许在表的一端进行插入&#xff0c;而在另一端进行删除元素。和平常我们排队打饭类似。 链队列是用链表表示的队列的简称。一个链队列需要两个分别指示队头和队尾的指针&#xff08;分…

请教一个算法问题,有两个数组A,B,判断A中是否至少有一个元素和B中元素相同...

最笨的办法当然是二层嵌套循环&#xff0c;但觉得应该有更好的方法&#xff0c;但是着实想不出来&#xff0c;想听听大家的意见&#xff0c;大家帮帮小弟 i.e string[] A{"X","Y","Z","W"}; string[] B{"X","E",&…

超市账单管理系统之-------登录

报500的错大部分都是springmvc的jar包没有导对&#xff0c;最好用3点几的版本 。。。。在项目中要把包导对 pom.xml 所需要的jar包 1 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"2 xs…

进制转换converse

栈和队列是在软件设计中常用的两种数据结构&#xff0c;它们的逻辑结构和线性表相同。 其特点在于运算受到了限制&#xff1a;栈按“后进先出”的规则进行操作&#xff0c;队按“先进先出”的规则进行操作&#xff0c;故称运算受限制的线性表。 从数据类型的角度看: 它们和线…

40.多进程同步--锁--多把锁

多进程同步 首先多进程默认是并发行为&#xff0c;多个进程同时执行执行的顺序&#xff0c;以及何时执行完毕无法控制 多个进程如果涉及到了通信&#xff0c;数据的有序性无法保证需要锁来控制进程之间执行的顺序对于进程资源的控制缺点&#xff1a;同步进程&#xff0c;并发没…

.net导出到Excel与Word中(带上下标)

//输出到excel的函数,可直接copy到 cs页面privatevoidOutExcel(GridView dg, stringname) { dg.Visible true; Response.Clear(); Response.Buffer true; Response.Charset "GB2312"; name "attachment;filename&quo…

越来越不想写代码了

越来越不想写代码了今天刚下载了PD12版本&#xff0c;做了一个需求分析以及试用了几个新功能在对C&#xff03;支持的情况。感觉非常不错&#xff0c;特别是在代码生成方面&#xff0c;比我想的要好多了&#xff0c;而且比起其它语言的代码生成&#xff0c;好像就是对C&#xf…

【代码笔记】Web-CSS-CSS id和Class选择器

一&#xff0c;效果图。 二&#xff0c;代码。 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>CSS id和class选择器</title> <style> #para1 { text-align: center; color: red; } .center { text-align: …

javascript取得鼠标的位置

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns"http://www.w3.org/1999/xhtml"><head><title>JavaScript得到鼠标坐标<…

nginx缓存功能的设置

首先用的缓存是proxy_cache. 在http段里加入下列几句&#xff1a; [plain] view plaincopy proxy_connect_timeout 5; proxy_read_timeout 60; proxy_send_timeout 5; proxy_buffer_size 16k; proxy_buffers 4 64k; proxy_busy_buffers_size 128k; proxy_tem…

线性表List的基本创建

#include <iostream> using namespace std; #include <malloc.h> #include <stdio.h> #define TURE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define IINFEASIBLE -1 #define OVERFLOW -2 typedef int Status; /*类型名定义用status代替int;Sta…

点点看   只有想不到没有看不到

看了这些好看的图片&#xff0c;不禁也想把自己看到的图片与大家一起分享了&#xff01;[url]http://mm-nn.com.cn/MM[/url]网[url]http://haotupic.cn/[/url]好图片网[url]http://www.picguan.cn/[/url]美女图片馆[url]http://www.nvyoou.cn/[/url]女友网[url]http://www.soft…

二叉树的基本应用知识总结

#include <iostream> using namespace std; #include <malloc.h> #include <stdio.h> #define TURE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define IINFEASIBLE -1 #define OVERFLOW -2#define MAX_TREE_SIZE 100//二叉树的最大结点数 typedef ch…

JS原生选项卡 – 幻灯片效果

1 <!DOCTYPE HTML>2 <html>3 <head>4 <meta charset"utf-8">5 <title>JS实现幻动片选项卡</title>6 </head>7 <style>8 .container{9 text-align:center; 10 width:100%; 11 } 12 13 .ppt{ …

MSSQL 2008里事务的一个问题

今天在试MSSQL2008里的事务&#xff0c;发现如果事务中某条语句的表名错误&#xff0c;就无法用error或try回滚&#xff0c;具体如下&#xff1a;begin tran delete from test where id 5 --正确语句 dealete from testa where id1 4 --表名错误&#xff0c;testa 表…

避免在JSP中写java代码

作者&#xff1a;蜗牛学院CTO李懿老师 ​自从十年前的taglibs&#xff08;如JSTL&#xff09;和EL&#xff08;表达语言&#xff0c;这些事情&#xff09;诞生以来&#xff0c;在JSP中使用scriptlet&#xff08;<% %>这些东西&#xff09;的确是非常不鼓励的。 小脚本的主…

爱情也许是最忧伤的童话

也许爱情是一部忧伤的童话 惟其遥远与真实 惟其不可触摸与欠缺 方可成就起璀璨与神圣 或许&#xff0c;只有在难得最远的时候&#xff0c; 才能把曾经走过的那段日子 看得最真切、最清楚 放弃一个很爱你的人&#xff0c;并不痛苦 放弃一个你很爱的人&#xff0c;那才痛苦 爱…

Docker最全教程——从理论到实战(六)

Docker最全教程——从理论到实战&#xff08;六&#xff09; 原文:Docker最全教程——从理论到实战&#xff08;六&#xff09;托管到腾讯云容器服务 托管到腾讯云容器服务&#xff0c;我们的公众号“magiccodes”已经发布了相关的录屏教程&#xff0c;大家可以结合本篇教程一起…

c#中分割字符串的几种方法

第一种方法&#xff1a;打开vs.net新建一个控制台项目。然后在Main()方法下输入下面的程序。 string s"abcdeabcdeabcde"; string[] sArrays.Split(c); foreach(string i in sArray) Console.WriteLine(i.ToString()); 输出下面的结果:ab deab deab de 我们看到了结果…

对相机所看的视角截屏保存为图片

对相机所看的视角截屏保存为图片&#xff1a; 1 using UnityEngine;2 using System.Collections;3 using UnityEngine.UI;4 /// <summary>5 /// 对相机截图6 /// </summary>7 public class Jietu : MonoBehaviour {8 9 public Camera camera; 10 Texture2D…

fsum函数测试以及分析

#include <stdio.h> #include <stdlib.h> #include <string.h>#define BUFSIZE 256//这是一句预定义&#xff0c;定义BUFSIZE的值是100&#xff0c;是缓冲空间的大小,作为数组的。int main(int argc, char *argv[]) //第一个int argc&#xff0c;是记录你输入…

oracle学习总结二(转义字符)

1、oracle 特殊字符 转义关键词&#xff1a; oracle 转义 环境&#xff1a;oracle 9i plsql在plsql里边执行:update userinfo set pageurlmyjsp?page1&pagesize10 where idtest这条sql语句往数据库的pageurl字段放进去了一…

C语言——冒泡法排序应用

#include <stdio.h> #include <stdlib.h> int main()/*有int main 就会有return 0;如果是void main ,就不用加上return 0了 */ {int i,j,temp;/*待会要用到&#xff0c;所以先定义,因为输入的都是整数&#xff0c;所以用int整数型*/int a[10];/*定义一个一维整型数…

2017 Multi-University Training Contest 3 hdu 6063

HDU 6063 思路&#xff1a; AC代码&#xff1a; #include "iostream" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set" #include "m…