研究牛人的程序struct-dump.h
来源:互联网 发布:2014网络女歌手名字 编辑:程序博客网 时间:2024/05/22 15:10
我大一的时候学习C语言,学过很多,有enum,struct union,但是没用过几次enum,今天研究源码突然发现个牛人的定义stuct-dump.h
enum desc_type { UINT64, SINT64, UINT32, SINT32, UINT16, SINT16, UINT8, SINT8, FOURCC, STRING, PTR, ENUM16, ENUM32, STRUCT, UNION, BITS16, BITS32, BITS64, VER, PADDING,};
看到了没,这个还不算什么呢,精彩的在这里
struct struct_desc {enum desc_type type; //这里用到了上面的枚举定义char *name;//姓名指针 unsigned int length;//无符号整型char **enums;//二维指针char **bits;struct struct_desc *desc; //自己调用自己!!!(都累死链表了)struct { //这里又是一个结构体,自信一看还是个数组!unsigned int value;char *name;struct struct_desc *desc; //有调用自己了,我的心啊,这是什么样的程序员啊!!!!!!!} u[16];};
上面的看不懂的话,下面的你可以理解,但是不知道咋用!
struct ioctl_desc {char *name;struct struct_desc *desc; //瞧,又是上面的吧};
这里来了全局变量的定义 结构体数组啊,没长度?
extern struct struct_desc desc_int[];extern struct struct_desc desc_long[];extern struct struct_desc desc_timeval[];/* ---------------------------------------------------------------------- */int print_struct(FILE *fp, struct struct_desc *desc, void *data, char *prefix, int tab);//就连函数也恨牛逼,文件指针fp,上面的牛逼结构体指针desc,无类型指针data,字符指针prefix,还有个tabint print_ioctl(FILE *fp, struct ioctl_desc *ioctls, char *prefix,int cmd, void *ptr);
以上部分是头文件,下面看看他的实现 struct-dump.c
看看这里用到的头
#include <stdio.h> //标准输入输出用#include <stdlib.h> //里面定义了五种类型、一些宏和通用工具函数#include <string.h> //关于字符数组的函数定义的头文件#include <inttypes.h> //这个是啥我没用过,查了下作用介绍如下#include <ctype.h> //字符处理,字符转换#include <sys/ioctl.h> //控制驱动通道的一些函数#include "struct-dump.h"
inttypes.h
定宽整型
诸如 uintptr_t 的有用类型
常量宏
限制
格式字符串宏
以下各节提供有关 <inttypes.h> 基本功能的更多信息。
定宽整型
<inttypes.h> 提供的定宽整型包括带符号整型(如 int8_t、int16_t、int32_t、int64_t)和无符号整型(如uint8_t、uint16_t、uint32_t、uint64_t)。
定义为可容纳规定位数的最短整型的派生类型包括 int_least8_t、int_least64_t、uint_least8_t、uint_least64_t 等。
对于循环计数器和文件描述符等操作,使用 int 或无符号 int 是安全的;对于数组索引,使用 long 也是安全的。但是,不应不加选择地使用这些定宽类型。可将定宽类型用于下列各项的显式二进制表示:
磁盘数据
通过数据线
硬件寄存器
二进制接口规范
二进制数据结构
诸如 unintptr_t 的有用类型
<inttypes.h> 文件包括大小足以容纳一个指针的带符号整型和无符号整型。这些类型以 intptr_t 和 uintptr_t 形式提供。此外,<inttypes.h> 还提供 intmax_t 和 uintmax_t,后两者是可用的最长(以位为单位)带符号整型和无符号整型。
使用 uintptr_t 类型作为指针的整型而非基本类型,如无符号 long。尽管在 ILP32 和 LP64 数据模型中,无符号long 与指针的长度相同,但如果使用uintptr_t,则在数据模型更改时,只有 uintptr_t 的定义受影响。这使您的代码可移植到许多其他系统中。它也是在 C 中更清楚地表达意图的方式。
需要执行地址运算时,intptr_t 和 uintptr_t 类型对于强制转换指针非常有用。因此,应使用 intptr_t 和uintptr_t 类型,而不是long 或无符号 long。
常量宏
使用宏 INT8_C(c)、INT64_C(c)、UINT8_C(c)、UINT64_C(c) 等指定给定常量的大小和符号。基本上,必要时这些宏会在常量的末尾添上l、ul、ll 或ull。例如,对于 ILP32,INT64_C(1) 会在常量 1 后面附加ll;对于 LP64,则附加 l。
可使用 INTMAX_C(c) 和 UINTMAX_C(c) 宏使常量成为最长类型。这些宏对于指定7.3 转换为 LP64 数据类型模型中介绍的常量类型会非常有用。
限制
由 <inttypes.h> 定义的限制是用于指定各种整型的最小值和最大值的常量,其中包括每个定宽类型的最小值(如 INT8_MIN、INT64_MIN 等)和最大值(如INT8_MAX、INT64_MAX 等)及其对应的无符号的最小值和最大值。
<inttypes.h> 文件还提供每个最短长度类型的最小值和最大值,其中包括 INT_LEAST8_MIN、INT_LEAST64_MIN、INT_LEAST8_MAX、INT_LEAST64_MAX 等及其对应的无符号的最小值和最大值。
最后,<inttypes.h> 还定义支持的最长整型的最小值和最大值,其中包括 INTMAX_MIN 和 INTMAX_MAX 及其对应的无符号的最小值和最大值。
格式字符串宏
<inttypes.h> 文件还包括指定 printf(3S) 和 scanf(3S) 格式说明符的宏。实质上,如果宏名称内置了参数的位数,这些宏将在格式说明符前面添加l 或ll,以便将参数标识为 long 或 long long。
printf(3S) 的宏以十进制、八进制、无符号和十六进制格式输出最短和最长整型,如以下示例所示:
int64_t i;printf("i =%" PRIx64 "\n", i);
同样,scanf(3S) 的宏以十进制、八进制、无符号和十六进制格式读取最短和最长整型。
uint64_t u;scanf("%" SCNu64 "\n", &u);
不要不加区别地使用这些宏。最好将它们与定宽整型中介绍的定宽类型一起使用。
这里还有源文件 http://duanple.blog.163.com/blog/static/70971767201031210480305/
上面的头文件介绍的太多了,网上找的给了地址,大家可以去看看。下面接着介绍
struct struct_desc desc_int[] = {{ //看看哪,上面的全局变量这里初始化是什么东西啊.type = SINT32, //type还加个' . ',搞的跟linux下驱动中定义结构体似的,计算下来就是SINT32==3.name = "int",},{ //这里注意了,按照结构体的定义这里有很多的东西要初始化,但是作者没有,这点的空结构体初始化有两个值,说明其占用了三个空间,这是我理解的/* end of list */}};struct struct_desc desc_long[] = {{.type = SINT32,.name = "long",},{/* end of list */}};struct struct_desc desc_timeval[] = {{/* FIXME *//* end of list */}};
下面是函数的一些定义
int print_struct(FILE *fp, struct struct_desc *desc, void *data, char *prefix, int tab){char name[256];unsigned char *ptr = data;uint64_t u64;int64_t s64;uint32_t u32;int32_t s32;uint16_t u16;int16_t s16;uint8_t u8;int8_t s8;int al = sizeof(long)-1; /* struct + union + 64bit alignment */ //不懂他注释里想表达什么void *p;unsigned int i,j,first;for (i = 0; desc[i].name != NULL; i++) {sprintf(name,"%s%s",prefix,desc[i].name); //把两个字符串合并为一个nameif (STRUCT == desc[i].type) {strcat(name,".");ptr = (void*)(((intptr_t)ptr + al) & ~al);//这句还真不懂 intptr_t == int * 右移al ;((int *)ptr+al) & ~al观点不一,有人说intptr_t == int ,迷茫了,我开始print_struct(fp,desc[i].desc, ptr, name, tab);//递归调用从0开始ptr += desc[i].length;if (!tab && desc[i+1].name != NULL)fprintf(fp,";");continue;}if (UNION == desc[i].type) { //这里的UNION是struct-dump.h中头文件定义的u32 = *((uint32_t*)(ptr-4));//减去4干吗呢?,左移4bit,为啥呢ptr = (void*)(((intptr_t)ptr + al) & ~al); //这里可能涉及到intptr_t == int *for (j = 0; desc[i].u[j].name != NULL; j++)if (desc[i].u[j].value == u32)break;if (desc[i].u[j].name != NULL) {strcat(name,".");strcat(name,desc[i].u[j].name);strcat(name,".");print_struct(fp,desc[i].u[j].desc, ptr, name, tab);}return 0; /* FIXME */}if (tab)fprintf(fp,"\t%-24s: ",name);elsefprintf(fp,"%s=",name);switch (desc[i].type) {case STRING:fprintf(fp,"\"%-.*s\"",desc[i].length,ptr);ptr += desc[i].length;break;case PTR:p = *(void**)ptr;fprintf(fp,"%p",p);ptr += sizeof(p);break;case VER:u32 = *((uint32_t*)ptr);fprintf(fp,"%d.%d.%d",(u32 >> 16) & 0xff,(u32 >> 8) & 0xff,u32 & 0xff);ptr += 4;break;case FOURCC:u32 = *((uint32_t*)ptr);fprintf(fp,"0x%08x [%c%c%c%c]", u32,isprint(ptr[0]) ? ptr[0] : '.',isprint(ptr[1]) ? ptr[1] : '.',isprint(ptr[2]) ? ptr[2] : '.',isprint(ptr[3]) ? ptr[3] : '.');ptr += 4;break;case ENUM16:u16 = *((uint16_t*)ptr);fprintf(fp,"%s", (u16 < desc[i].length && desc[i].enums[u16])? desc[i].enums[u16] : "unknown");ptr += 2;break;case ENUM32:u32 = *((uint32_t*)ptr);fprintf(fp,"%s", (u32 < desc[i].length && desc[i].enums[u32])? desc[i].enums[u32] : "unknown");ptr += 4;break;case BITS16:u16 = *((uint16_t*)ptr);first = 1;fprintf(fp,"0x%x [",u16);for (j = 0; j < 16; j++) {if (0 == (u16 & (1 << j)))continue;fprintf(fp,"%s%s",first ? "" : ",",desc[i].bits[j]);first = 0;}fprintf(fp,"]");ptr += 2;break;case BITS32:u32 = *((uint32_t*)ptr);first = 1;fprintf(fp,"0x%x [",u32);for (j = 0; j < 32; j++) {if (0 == (u32 & (1 << j)))continue;fprintf(fp,"%s%s",first ? "" : ",",desc[i].bits[j]);first = 0;}fprintf(fp,"]");ptr += 4;break;case BITS64:ptr = (void*)(((intptr_t)ptr + al) & ~al);u64 = *((uint64_t*)ptr);first = 1;fprintf(fp,"0x%" PRIx64 " [",u64);for (j = 0; j < 64; j++) {if (0 == (u64 & ((int64_t)1 << j)))continue;fprintf(fp,"%s%s",first ? "" : ",",desc[i].bits[j]);first = 0;}fprintf(fp,"]");ptr += 8;break;case UINT64:ptr = (void*)(((intptr_t)ptr + al) & ~al);u64 = *((uint64_t*)ptr);fprintf(fp,"%" PRIu64,u64);ptr += 8;break;case SINT64:ptr = (void*)(((intptr_t)ptr + al) & ~al);s64 = *((int64_t*)ptr);fprintf(fp,"%" PRId64,s64);ptr += 8;break;case UINT32:u32 = *((uint32_t*)ptr);fprintf(fp,"%u",u32);ptr += 4;break;case SINT32:s32 = *((int32_t*)ptr);fprintf(fp,"%d",s32);ptr += 4;break;case UINT16:u16 = *((uint16_t*)ptr);fprintf(fp,"%u",u16);ptr += 2;break;case SINT16:s16 = *((int16_t*)ptr);fprintf(fp,"%d",s16);ptr += 2;break;case UINT8:u8 = *((uint8_t*)ptr);fprintf(fp,"%u",u8);ptr += 1;break;case SINT8:s8 = *((int8_t*)ptr);fprintf(fp,"%d",s8);ptr += 1;break;case PADDING:ptr += desc[i].length;break;case STRUCT:case UNION:/* shouldn't happen */fprintf(fp,"FIXME [type=%d]\n",desc[i].type);exit(1);}if (tab)fprintf(fp,"\n");else if (desc[i+1].name != NULL)fprintf(fp,";");}return 0;}/* ---------------------------------------------------------------------- */int print_ioctl(FILE *fp, struct ioctl_desc *ioctls, char *prefix,int cmd, void *ptr){int index = _IOC_NR(cmd);char *name = ioctls[index].name;struct struct_desc *desc = ioctls[index].desc;fprintf(fp,"%s%s(", prefix, name ? name : "UNKNOWN");if (desc) {print_struct(fp,desc,ptr,"",0);} else {fprintf(stderr,"???");}fprintf(fp,")");return 0;}/* ---------------------------------------------------------------------- *//* * Local variables: * c-basic-offset: 8 * End: */
- 研究牛人的程序struct-dump.h
- gcc的 "-fpack-struct" 编译选项导致程序core dump的分析
- dump日志文件的内容的研究
- B*树索引的dump研究
- 生成dump的程序方法
- struct ip 和struct iphdr的差别 , <netinet/*.h>和<linux/*.h>
- 程序崩溃 dump 文件 *.kdmp的使用
- 程序崩溃 dump 文件 *.kdmp的使用
- 我的程序又core dump了
- VS调试C#程序产生的dump
- struct 结构 研究
- struct结构会增加程序的开销
- dump struct sw_flow from vport/datapath
- 使用WinDbg抓取程序报错的Dump文件,例如抓取IE崩溃的Dump
- java程序性能分析用到的文件thread dump和heap dump入门
- core dump 调试程序
- Linux系统dameon程序的core dump设置
- [转载]用dumper打开运行程序的core dump功能
- Linux平台上如何使用接静态库和共享库
- iphone 实现截屏的函数
- IPhone开发中的HTTP链接问题
- 消息称电信将于10月引入两款CDMA版iPhone
- NIO中异步IO的完整实现实例
- 研究牛人的程序struct-dump.h
- 黑马程序员--javaAPI
- linux查看硬件信息及驱动设备相关整理(留存验证)
- Android 获取自己程序APK包的MD5指纹
- DWR的异常处理及session过期
- Ubuntu桌面版讨论使用全局菜单和取消的命令
- 入侵软件学习
- sql 连接字符串大全
- 2003 计划任务