把握clock_t 在系统中实际是什么类型,有助于编程 人员更好的使用该类型的变量,最直接的好处就是可以防止变量溢出,在溢出时能够准确判断可能存在问题的代码。现就将clock_t 的查找过程做简单记录。
1)
首先使用clock_t 类型变量需要包含<time.h>头文件,因此到该头文件中查找,而<time.h>位于哪里,使用locate命令进行查找。为什么使用locate命令可以参考这篇blog:http://blog.csdn.net/ysdaniel/article/details/7043298
通过locate命令查找后可以发现仅<time.h>在不同文件夹下就有多个,因此哪一个<time.h>是我们要查找的,这涉及头文件的查找顺序,可参考这篇blog:http://blog.csdn.net/chosen0ne/article/details/7210946
根据以上blog中的内容,在编译时未使用-I选项,C_INCLUDE_PATH与CPLUS_INCLUDE_PATH路径为空,因此<time.h>位于/usr/include中。终于确定了time.h 的位置。
2)
在<time.h>中直接查找,clock_t,可以找到如下定义
#if !defined __clock_t_defined && (defined _TIME_H || defined __need_clock_t)
# define __clock_t_defined 1
# include <bits/types.h>
__BEGIN_NAMESPACE_STD
/* Returned by `clock'. */
typedef __clock_t clock_t;
__END_NAMESPACE_STD
#if defined __USE_XOPEN || defined __USE_POSIX
__USING_NAMESPACE_STD(clock_t)
#endif
在文件中无法找到__clock_t 的类型定义,不过发现包含<bits/types.h>。
3)
因此采用相同的方法,发现bits文件夹位于/usr/include/x86_64-linux-gnu/下,<type.h>中相关内容如下:
#include <bits/typesizes.h>
# define __STD_TYPE typedef
__STD_TYPE __CLOCK_T_TYPE __clock_t; /* Type of CPU usage counts. */
依然无法进一步找到__CLOCK_T_TYPE的类型,同时发现包含<bits/typesizes.h>。
4)
在<typesizes.h>中查找__CLOCK_T_TYPE的相关内容如下:
/* See <bits/types.h> for the meaning of these macros. This file exists so
that <bits/types.h> need not vary across different GNU platforms. */
#define __CLOCK_T_TYPE __SYSCALL_SLONG_TYPE
再次查找__SYSCALL_SLONG_TYPE的内容,可找到如下内容
#if defined __x86_64__ && defined __ILP32__
# define __SYSCALL_SLONG_TYPE __SQUAD_TYPE
# define __SYSCALL_ULONG_TYPE __UQUAD_TYPE
#else
# define __SYSCALL_SLONG_TYPE __SLONGWORD_TYPE
# define __SYSCALL_ULONG_TYPE __ULONGWORD_TYPE
#endif
由于我的机器是64位,因此__SYSCALL_SLONG_TYPE类型为__SQUAD_TYPE,到此查找过程实际已进入死路,因为<typesizes.h>不再包含其他头文件,不过根据注释的内容,相同的宏定义在<types.h> 中,因此回到<types.h>。
5)
在<types.h>中直接查找__SQUAD_TYPE,可得相关内容如下:
#define __S16_TYPE short int
#define __U16_TYPE unsigned short int
#define __S32_TYPE int
#define __U32_TYPE unsigned int
#define __SLONGWORD_TYPE long int
#define __ULONGWORD_TYPE unsigned long int
#if __WORDSIZE == 32
# define __SQUAD_TYPE __quad_t
# define __UQUAD_TYPE __u_quad_t
# define __SWORD_TYPE int
# define __UWORD_TYPE unsigned int
# define __SLONG32_TYPE long int
# define __ULONG32_TYPE unsigned long int
# define __S64_TYPE __quad_t
# define __U64_TYPE __u_quad_t
/* We want __extension__ before typedef's that use nonstandard base types
such as `long long' in C89 mode. */
# define __STD_TYPE __extension__ typedef
#elif __WORDSIZE == 64
# define __SQUAD_TYPE long int
# define __UQUAD_TYPE unsigned long int
# define __SWORD_TYPE long int
# define __UWORD_TYPE unsigned long int
# define __SLONG32_TYPE int
# define __ULONG32_TYPE unsigned int
# define __S64_TYPE long int
# define __U64_TYPE unsigned long int
/* No need to mark the typedef with __extension__. */
# define __STD_TYPE typedef
#else
# error
#endif
#include <bits/typesizes.h> /* Defines __*_T_TYPE macros. */
好了结果出来了,__SQUAD_TYPE类型为long int,即clock_t经过多重宏定义会被转换为long int。在编译时被包含的头文件会在包含文件中展开,__SYSCALL_SLONG_TYPE会被替换为long int,之后回溯的内容以此类推。
恩,恭喜你看到了这里。其实要知道clock_t 类型远不用这么麻烦,可以在编译时使用-E选项,-E选项的作用主要是对#include文件进行展开,并将#define的内容进行替换。
写一个简答的测试程序,#include<stdio.h>都不要了,只要#include<time.h>,测试程序如下:
#include <time.h>
int main()
{
clock_t argu;
return 0;
}
运行以下命令:
gcc -E -o test_clock_t.i test_clock_t.c
相关内容如下:
typedef long int __clock_t;
typedef __clock_t clock_t;
int main()
{
clock_t argu;
}
通过实验也可以发现,预编译过程对typedef不起作用。