"没有升迁发财,没有大牛小白,挖掘工程的背后是回归最初兴趣的源动力。“

                                                                                       ----火星人

  size_t 一直是c/c++频道的一线演员,他几乎出现在该频道的每一部连续剧当中,扮演着正义完美没有不良记录的角色。曾经有一段时间,Mars以为这位影星是从stddef.h出道的,不过当他在redhat和mac上写了一个简单的c程序,里面只包含一个stdio.h文件时,他发现size_t已经栖身其中。此篇就是dig一下size_t在用户程序崭露头角之前是怎么诞生的,此篇只讲述Mac OSX下的情况,戴红帽的那群兄弟,你们冷静点,本篇结尾会给你们交待的。

  既然要找出size_t的定义源头,那就少不了研究头文件的包含顺序。勤奋朴实的Mars在刚开始那些日子里采用的方法就是用肉眼和大脑去分析这个顺序,当然这是一个很复杂的过程,而且这样的出来的结果说服力不高,因为难保顺序根本不是Mars所推测的那样。

  某一天当Mars正为这个问题发愁的时候,他想起了gcc那拥有远古黑魔法的编译选项——"-E",于是他研究出来下面这套衍生命令:

gcc -E demo.cpp |  grep -P "^#" | grep -o "\".*\"" | uniq | less

demo.cpp是上面提到的程序(哎呀,就是那个只有#include<stdio.h>和空main的程序啦)。

这个命令干了啥不是此篇的重点,电视机前的观众或许已经心中有数,没数的自己去研究一下或者等Mars喝过可口的星巴克之后再书一篇关于这个的。

黑魔法炼金术施放之后出来的成品如下:

红色框框里面的不是死刑对象,虽然小学老师告诉Mars不能随便用红色,但麦当劳叔叔也说了,“我就喜欢!”。经过亲自分析之后,红框里面的5个header以及其顺序就是size_t诞生的过程,还等什么?马上进入实证的探寻过程!BOSS就在里面!

  在/usr/include/stdio.h中,有着size_t的直接定义:

 76 #ifndef _SIZE_T77 #define _SIZE_T78 typedef __darwin_size_t         size_t;79 #endif

而在下一步/usr/include/_types.h中,__darwin_size_t的身影消失得无影无踪,显然是躲到迷宫的下一层去了!(RPG迷“嗯”了一声,想起那曾经找过的BOSS)

  来到了/usr/include/sys/_types.h这一层还是晚了,但Mars看了一眼这一层的鬼斧神工,里面展示了无数构造系统的类型定义源头,他知道以后他还是会回来这里的。

  /usr/include/machine/_types.h只是一个分岔口,除去2/3的开场路牌注释,剩下的有效代码只有不够10行,没错,这个header的作用是用来决定具体机器平台的类型,然后才知道BOSS的真正所在,因为Mars的macbook pro是x86架构的,于是就leader着到最后一层。

 28 #ifndef _BSD_MACHINE__TYPES_H_29 #define _BSD_MACHINE__TYPES_H_30 31 #if defined (__i386__) || defined(__x86_64__)32 #include "i386/_types.h"33 #elif defined (__arm__)34 #include "arm/_types.h"35 #else36 #error architecture not supported37 #endif38 39 #endif /* _BSD_MACHINE__TYPES_H_ */

  在/usr/include/i386/_types.h中,找到了她,但却发现并不是他心中的那个她:

 89 #if defined(__GNUC__) && defined(__SIZE_TYPE__)90 #define MARS_ENTER_HERE 191 typedef __SIZE_TYPE__           __darwin_size_t;        /* sizeof() */92 #else93 typedef unsigned long           __darwin_size_t;        /* sizeof() */94 #endif

通过自定义宏这招(不会不理解吧?),实证得知真正执行的定义代码是

typedef __SIZE_TYPE__    __darwin_size_t;

这一次RPG铁粉们实在不能忍了,这完全就是最终打败BOSS之后还留下续集的伏笔啊,什么__SIZE_TYPE__啊,银河系里又一大魔头吗!!Mars决定不等待续集的发布,直接在本集KO下集的BOSS,于是他又捡起了地上的宝剑......

  尽管在其他头文件里面乱找一通,但也没能看到__SIZE_TYPE__的踪影,不用怕,地球上还存在这样的咒语来检验真理的标准:

#if defined(__GNUC__)
#define MARS__GNUC__DEFINED 1
#else
#define MARS__GNUC__DEFINED 0
#endif#if defined(__SIZE_TYPE__)
#define MARS__SIZE_TYPE__DEFINED 1
#else
#define MARS__SIZE_TYPE__DEFINED 0
#endif

#include <stdio.h>

注意#include <stdio.h>是在最下面的,在此之前已经没有任何header来干扰真理的检验。实证结果是在包含一切header之前,__GNUC__和__SIZE_TYPE__已经被定义了,他们真的是续集的BOSS!为了不引起地球人的暴动,还得找出更加官方的信息来支持这一说,于是Mars第一次游进了gcc的标准文档之海.......

  在gcc标准文档中打滚过的兄弟姐妹们都知道里面什么情况,捣腾了接近一个小时,下面这段文字终于被翻出来:

__SIZE_TYPE__

__PTRDIFF_TYPE__

__WCHAR_TYPE__

__WINT_TYPE__

__INTMAX_TYPE__

__UINTMAX_TYPE__

These macros are defined to the correct underlying types for the size_t, ptrdiff_t, wchar_t, wint_t, intmax_t, and uintmax_t typedefs, respectively. They exist to make the standard header files stddef.h and wchar.h work correctly. You should not use these macros directly; instead, include the appropriate headers and use the typedefs.

文档位置是:http://gcc.gnu.org/onlinedocs/gcc-4.2.4/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros

  其实好多技术文章都会把官方文档中的英文亮一下以示高贵和镀金,但接下来都会跟着一段屌丝的翻译。这段鸡肠大概的意思就是这几个好基友macro是gcc用来表示机器级别的数值类型,然后这些数值类型又被stddef.h一翻烹调过后最终递到大伙面前,成为c标准下的那些大明星,其中之一就包括此篇的主角——size_t。

  好了,来到这里Mars已经超班BUG杀了小BOSS——__SIZE_TYPE__,最后Mars还是能找到size_t的真实身份——一个GCC预定义的数值类型,当然这个类型是可以在编译时修改的,但敢不敢改就另当别论了,毕竟他可是渗透全球的知名人物呢。但这只是在Mac OS X下的情况;redhat下的情况有点不一样,在那边涉及到上面提到的stddef.h,马上会有另一篇专门dig这位大家闺秀的背后。

转载于:https://www.cnblogs.com/mmars/archive/2013/05/06/3062546.html

藏身于stdio.h中的size_t相关推荐

  1. C语言基础-#include<stdio.h>

    #include<stdio.h> 告诉编译器把stdio.h中的内容包含在当前程序中. stdio.h是c编译器软件包的标准部分,它提供键盘输入和屏幕输出的支持.

  2. stdio.h头文件包含的函数有哪些?

    stdio.h 以下来自维基百科中文 多数与C语言输入输出相关的函数在<stdio.h>中定义(C++中的<cstdio>). 文件访问 fopen freopen fflus ...

  3. C 标准库 (stdio.h 介绍)

    <stdio.h>     1.简介           2.库变量 3.宏函数 4.库函数 4.1 关闭流 stream.刷新所有的缓冲区.   int fclose(FILE *str ...

  4. stdio.h头文件中申明的基本函数

    stdio.h头文件中申明的基本函数 调用scanf函数时,需传入变量的地址作为参数,scanf函数会等待标准输入设备(键盘等)输入数据,并且将输入的数据赋值给地址对应的变量. #include< ...

  5. php中h语言是什么意思,stdio.h是什么意思?

    stdio.h全称"standard input output.header",中文意思为"标准输入输出头文件",在用到标准输入输出函数时,就要调用这个头文件: ...

  6. 【C++】关于C++中使用namespace的解释以及cstdio和stdio.h的区别

    引言 你有没有想过,在C++中,我们经常使用一句using namespace std;这样一句话,但是具体是什么含义呢? 你有没有想过,为什么使用printf()函数的时候,在C语言中是#inclu ...

  7. C语言中的 #include <stdio.h>是什么?

    最近在学习C语言基础的时候,我注意到了在写代码时经常使用的 #include <stdio.h>.众所周知,这是引用头文件的操作,但对于它的深层次含义,我并没有更多的了解.所以今天就来让我 ...

  8. stdio.h: C++输入输出操作

    头文件:<stdio.h>.<cstdio> 1.通过"streams"来操作物理设备:如键盘.打印机.终端等. 2.流通过指针来连接"FILE& ...

  9. C语言 标准I/O库: stdio.h

    C Primer Plus附录中列出了stdio.h的一系列库函数. void clearerr(FILE *); 清除文件结尾和错误指示符 int fclose(FILE *); 关闭指定的文件 i ...

最新文章

  1. LinkedList 真的是查找慢增删快?
  2. 部署项目到阿里云服务器上遇到的问题
  3. python英文字典小程序_python 字典所有操作
  4. python用变量输出abcd_python中星号变量的几种特殊用法
  5. yii2数组转为对象_好程序员Java学习路线分享java为什么不支持泛型数组
  6. 网络编程第三讲UDP编写
  7. 如何给腾讯云域名申请免费的SSL证书
  8. java类验证和装载顺序_Java类的加载机制和双亲委派模型
  9. java ajax报错500,(Struts2+JSON+Ajax) XMLHttpRequest ==500如何解决
  10. android sp wp实例,android sp wp详解
  11. sata接口_解决主板SATA接口不足:乐扩PCIe2.0转8口SATA3/6G扩展卡
  12. mediarecorder 录制的文件无法拖动进度条_如何下载网络ts视频文件
  13. 随想录(qemu的学习)
  14. vscode彩色括号
  15. Oracle函数保留两位小数
  16. “用户体验及可用性测试”前三章:读书笔记
  17. Java中获取当前时间
  18. 女神模特网站源码_套图下载 GBK+UTF Discuz模板
  19. 一款公历转农历节气以及天干地支的js代码
  20. CF850D Tournament Construction

热门文章

  1. 【测控电路】微积分电路
  2. 一个程序员的基本素质
  3. LabVIEW读取电子表格的例子
  4. 自动化处理--python读取word中表格内容
  5. 储能系统,基于下垂控制储能soc均衡控制。 通过引入加速因子k,在保证功率合理分配的同时,有效提升soc均衡速度
  6. Ubuntu18 USB网卡驱动安装踩坑记录
  7. 使用SoftICE破解Winzip8.0全攻略
  8. Java图片加文字水印
  9. thinkpad x200 自己更换风扇的步骤和更换后的调整
  10. 取余c语言输入一行中一个正整数n pta,正整数