现在的位置: 首页 > 综合 > 正文

glibc之数据类型定义分析

2013年08月18日 ⁄ 综合 ⁄ 共 3869字 ⁄ 字号 评论关闭

  本文主要涉及到的库文件位于/usr/include/bits目录下,文件包括wordsize.h,types.h,typesizes.h 等文件。

  wordsize.h中主要定义了当前机器的字大小。内容如下:

  ...

  #define __WORDSIZE  32

  ...

 

  这里的宏应该是安装系统的时候,确定的机器字的大小,然后才生成对应的宏。这个宏会在types.h中作为判定条件,从而定义相应数据类型。我们可以看下types.h文件有如下内容:

 

   99 #define __S16_TYPE      short int
100 #define __U16_TYPE      unsigned short int
101 #define __S32_TYPE      int

102 #define __U32_TYPE      unsigned int
103 #define __SLONGWORD_TYPE    long int
104 #define __ULONGWORD_TYPE    unsigned long int

//以上类型定义与机器字长度无关
105 #if __WORDSIZE == 32

106 # define __SQUAD_TYPE       __quad_t
107 # define __UQUAD_TYPE       __u_quad_t
108 # define __SWORD_TYPE       int
109 # define __UWORD_TYPE       unsigned int
110 # define __SLONG32_TYPE     long int
111 # define __ULONG32_TYPE     unsigned long int
112 # define __S64_TYPE     __quad_t
113 # define __U64_TYPE     __u_quad_t
114 /* We want __extension__ before typedef's that use nonstandard base types
115    such as `long long' in C89 mode.  */
116 # define __STD_TYPE     __extension__ typedef //如果机器为32位,我们需要使用扩展数据类型定义宏

117 #elif __WORDSIZE == 64

118 # define __SQUAD_TYPE       long int
119 # define __UQUAD_TYPE       unsigned long int
120 # define __SWORD_TYPE       long int
121 # define __UWORD_TYPE       unsigned long int
122 # define __SLONG32_TYPE     int
123 # define __ULONG32_TYPE     unsigned int
124 # define __S64_TYPE     long int
125 # define __U64_TYPE     unsigned long int
126 /* No need to mark the typedef with __extension__.   */
127 # define __STD_TYPE     typedef

//如果机器为64位,我们不需要在typedef前加扩展宏
__extension__,后面的__STD_TYPE 即表示typedef
128 #else

129 # error
130 #endif

 

上面的# define __SQUAD_TYPE       __quad_t表示当机器为32位,但是又要表示64位数据时,我们可以通过如下方法定义:

 /* quad_t is also 64 bits.  */
 52 #if __WORDSIZE == 64
 53 typedef long int __quad_t;
 54 typedef unsigned long int __u_quad_t;
 55 #elif defined __GLIBC_HAVE_LONG_LONG
 56 __extension__ typedef long long int __quad_t;
 57 __extension__ typedef unsigned long long int __u_quad_t;
 58 #else //32位机器
 59 typedef struct
 60 {
 61   long __val[2];
 62 } __quad_t;
 63 typedef struct
 64 {
 65   __u_long __val[2];
 66 } __u_quad_t;


 67 #endif

 

 

131 #include <bits/typesizes.h> /* Defines __*_T_TYPE macros.  */

//将typesizes.h包含进来,因为里面通过定义了所有的 __*_T_TYPE宏,而这些宏都是下面的类型定义的基础

135 __STD_TYPE __UID_T_TYPE __uid_t;    /* Type of user identifications.  */
136 __STD_TYPE __GID_T_TYPE __gid_t;    /* Type of group identifications.  */
143 __STD_TYPE __PID_T_TYPE __pid_t;    /* Type of process identifications.  */
155 __STD_TYPE __KEY_T_TYPE __key_t;    /* Type of an IPC key.  */

 

注意这里的__STD_TYPE = typedef 不再是宏定义,而是类型定义

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

我们可以查看typesizes.h文件,内容如下:

  1 /* bits/typesizes.h -- underlying types for *_t.  Generic version.

       这个文件用来定义类似于*_t的基本类型(underlying type)

        .....
  2  */
 19
 20 #ifndef _BITS_TYPES_H
 21 # error "Never include <bits/typesizes.h> directly; use <sys/types.h> instead."
 22 #endif
 23
 24 #ifndef _BITS_TYPESIZES_H
 25 #define _BITS_TYPESIZES_H   1
 26
 27 /* See <bits/types.h> for the meaning of these macros.  This file exists so
 28    that <bits/types.h> need not vary across different GNU platforms. 

         宏定义参考types.h中的宏定义,如__S32_TYPE 这个是在types.h中定义的。

         #define __S32_TYPE      int

        至于为什么要这么交叉定义,是为了使types.h不因为平台而发生变化。

        因为,如果不同的平台的话,我们只需要改变typesizes.h就可以了。

*/
 
 31 #define __UID_T_TYPE        __U32_TYPE
 32 #define __GID_T_TYPE        __U32_TYPE
 39 #define __PID_T_TYPE        __S32_TYPE
 53 #define __DADDR_T_TYPE      __S32_TYPE

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

 

我们以__key_t为例子来寻定义的蛛丝马迹:

1.__STD_TYPE   __KEY_T_TYPE   __key_t            //bits/types.h

2.#define  __KEY_T_TYPE   __S32_TYPE              //bits/typesizes.h

3.#define  __S32_TYPE  int

 

从3-2-1就是我们的: typedef int   __key_t ;

 

至于我们看到的ipc中的key_t数据类型,则又是在__key_t基础上定义的,我们可以在ipc.h中找到这个定义:

 

 47 #ifndef __key_t_defined
 48 typedef __key_t key_t;
 49 # define __key_t_defined
 50 #endif

 

所以,我们在linux c 编程里面经常看到的那些莫名奇妙的数据类型,基本都可以通过以上方式找到最终的基本数据类型。

 

 

 

抱歉!评论已关闭.