研究牛人的程序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

include 文件 <inttypes.h> 提供有助于使代码与显式指定大小的数据项兼容(无论编译环境如何)的常量、宏和派生类型。它包含用于处理 8 位、16 位、32 位和 64 位对象的机制。该文件是新的 1999 ISO/IEC C 标准的一部分,文件内容反映了导致它包含在 1999 ISO/IEC C 标准中的建议。文件即将更新,以便完全与 1999 ISO/IEC C 标准一致。<inttypes.h> 提供的基本功能包括:

  • 定宽整型

  • 诸如 uintptr_t 的有用类型

  • 常量宏

  • 限制

  • 格式字符串宏

以下各节提供有关 <inttypes.h> 基本功能的更多信息。

定宽整型

<inttypes.h> 提供的定宽整型包括带符号整型(如 int8_tint16_tint32_tint64_t)和无符号整型(如uint8_tuint16_tuint32_tuint64_t)。

定义为可容纳规定位数的最短整型的派生类型包括 int_least8_tint_least64_tuint_least8_tuint_least64_t 等。

对于循环计数器和文件描述符等操作,使用 int 或无符号 int 是安全的;对于数组索引,使用 long 也是安全的。但是,不应不加选择地使用这些定宽类型。可将定宽类型用于下列各项的显式二进制表示:

  • 磁盘数据

  • 通过数据线

  • 硬件寄存器

  • 二进制接口规范

  • 二进制数据结构

诸如 unintptr_t 的有用类型

<inttypes.h> 文件包括大小足以容纳一个指针的带符号整型和无符号整型。这些类型以 intptr_tuintptr_t 形式提供。此外,<inttypes.h> 还提供 intmax_tuintmax_t,后两者是可用的最长(以位为单位)带符号整型和无符号整型。

使用 uintptr_t 类型作为指针的整型而非基本类型,如无符号 long。尽管在 ILP32 和 LP64 数据模型中,无符号long 与指针的长度相同,但如果使用uintptr_t,则在数据模型更改时,只有 uintptr_t 的定义受影响。这使您的代码可移植到许多其他系统中。它也是在 C 中更清楚地表达意图的方式。

需要执行地址运算时,intptr_tuintptr_t 类型对于强制转换指针非常有用。因此,应使用 intptr_tuintptr_t 类型,而不是long 或无符号 long

常量宏

使用宏 INT8_C(c)INT64_C(c)UINT8_C(c)UINT64_C(c) 等指定给定常量的大小和符号。基本上,必要时这些宏会在常量的末尾添上lulllull。例如,对于 ILP32,INT64_C(1) 会在常量 1 后面附加ll;对于 LP64,则附加 l。

可使用 INTMAX_C(c)UINTMAX_C(c) 宏使常量成为最长类型。这些宏对于指定7.3 转换为 LP64 数据类型模型中介绍的常量类型会非常有用。

限制

<inttypes.h> 定义的限制是用于指定各种整型的最小值和最大值的常量,其中包括每个定宽类型的最小值(如 INT8_MININT64_MIN 等)和最大值(如INT8_MAXINT64_MAX 等)及其对应的无符号的最小值和最大值。

<inttypes.h> 文件还提供每个最短长度类型的最小值和最大值,其中包括 INT_LEAST8_MININT_LEAST64_MININT_LEAST8_MAXINT_LEAST64_MAX 等及其对应的无符号的最小值和最大值。

最后,<inttypes.h> 还定义支持的最长整型的最小值和最大值,其中包括 INTMAX_MININTMAX_MAX 及其对应的无符号的最小值和最大值。

格式字符串宏

<inttypes.h> 文件还包括指定 printf(3S)scanf(3S) 格式说明符的宏。实质上,如果宏名称内置了参数的位数,这些宏将在格式说明符前面添加lll,以便将参数标识为 longlong 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: */