说到宏,您可能会想到它常见的两个例子:
#define BUFFER_SIZE 1024
#define min(X, Y)  ((X) < (Y) ? (X) : (Y))
        更多关于宏的介绍,请查看GCC-OnlineDoc-Macros. 现在让我们来看下面这段代码,摘自Git的初始提交,没错Linus Torvalds写的那个Git. 当您克隆其仓库到本地后,您可以通过git checkout e83c5163316f89bfbde7d9ab23ca2e25604af290命令签出其初始提交。
#ifdef BGIT_UNIX
    #define STAT_TIME_SEC( st, st_xtim ) ( (st)->st_xtim ## e )
    #define STAT_TIME_NSEC( st, st_xtim ) ( (st)->st_xtim.tv_nsec )
#elif defined BGIT_DARWIN
    #define STAT_TIME_SEC( st, st_xtim ) ( (st)->st_xtim ## espec.tv_sec )
    #define STAT_TIME_NSEC( st, st_xtim ) ( (st)->st_xtim ## espec.tv_nsec )
#elif defined BGIT_WINDOWS
    #define STAT_TIME_SEC( st, st_xtim ) ( (st)->st_xtim ## e )
    #define STAT_TIME_NSEC( st, st_xtim ) 0
#endif
上面那段代码,说到底是为了统一不同环境(Unix, Darwin, Windows)下对stat结构体中文件时间的访问(包括秒和纳秒)
        实际上,在Unix系统下,您是通过(st)->st_ctim.tv_sec访问文件的创建时间(秒),而在MacOSX系统下,您是通过(st)->st_ctimespec.tv_sec访问文件的创建时间(秒)
        在Linux下,您可以分别通过gcc -E show-diff.c -o show-diff-unix.i -D BGIT_UNIX和gcc -E show-diff.c -o show-diff-darwin.i -D BGIT_DARWIN命令生成经过预处理后的代码文件。
观察生成的show-diff-unix.i和show-diff-darwin.i文件和show-diff.c源文件,您可以发现原来代码文件中的下面这一段:
/* Check last modification time. */
if (ce->mtime.sec  != (unsigned int)STAT_TIME_SEC( st, st_mtim ) ||
    ce->mtime.nsec != (unsigned int)STAT_TIME_NSEC( st, st_mtim ))
        changed |= MTIME_CHANGED;
在定义了BGIT_UNIX环境变量的情况下被展开成:
if (ce->mtime.sec != (unsigned int)( (st)->st_mtim.tv_sec ) ||
    ce->mtime.nsec != (unsigned int)( (st)->st_mtim.tv_nsec ))
        changed |= 0x0001;
在定义了BGIT_DARWIN环境变量的情况下被展开成:
if (ce->mtime.sec != (unsigned int)( (st)->st_mtimespec.tv_sec ) ||
    ce->mtime.nsec != (unsigned int)( (st)->st_mtimespec.tv_nsec ))
        changed |= 0x0001;
        您可能发现这里有个问题,当BGIT_UNIX环境变量存在时候,STAT_TIME_SEC( st, st_mtim )应该会被展开成(st)->st_mtime才对。那为什么我们上面经过预处理的代码中会变成(st)->st_mtim.tv_sec )呢?
        答案在stat结构体:
struct stat {
   dev_t st_dev; /* ID of device containing file */
   ino_t st_ino; /* inode number */
   mode_tst_mode;/* protection */
   nlink_t   st_nlink;   /* number of hard links */
   uid_t st_uid; /* user ID of owner */
   gid_t st_gid; /* group ID of owner */
   dev_t st_rdev;/* device ID (if special file) */
   off_t st_size;/* total size, in bytes */
   blksize_t st_blksize; /* blocksize for filesystem I/O */
   blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
   /* Since Linux 2.6, the kernel supports nanosecond
  precision for the following timestamp fields.
  For the details before Linux 2.6, see NOTES. */
   struct timespec st_atim;  /* time of last access */
   struct timespec st_mtim;  /* time of last modification */
   struct timespec st_ctim;  /* time o f last status change */
   #define st_atime st_atim.tv_sec  /* Backward compatibility */
   #define st_mtime st_mtim.tv_sec
   #define st_ctime st_ctim.tv_sec
};
        留意最后三行,原来STAT_TIME_SEC( st, st_mtim )先被展开成(st)->st_mtime,而后又被展开成(st)->st_mtim.tv_sec ).
原文:https://www.cnblogs.com/lukeaxu/p/14723481.html