首页 > 其他 > 详细

Git代码中的宏

时间:2021-04-30 23:41:56      阅读:33      评论:0      收藏:0      [点我收藏+]

宏是什么?

        说到宏,您可能会想到它常见的两个例子:

#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_UNIXgcc -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 ).

\[--END-- \]

Git代码中的宏

原文:https://www.cnblogs.com/lukeaxu/p/14723481.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!