Some tips in C

libstdc

  1. opendir()打开目录后,目录内容发生改变,readdir()则不能正确获得目录内容。虽 然概率很低,还是会发生地
  2. rename()不能跨mount point重命名文件,会返回EBUSY。移动、复制文件很复杂,可 以参考coreutilssrc/copy.c的实现。

Playing with macro

  1. 多条语句的宏用do { ... } while(0)括住
  2. Round up to power of 2: (uint32_t only)
    #define round_up_to_next_power_of_2(v) do { \
        v--; \
        v |= v >> 1; \
        v |= v >> 2; \
        v |= v >> 4; \
        v |= v >> 8; \
        v |= v >> 16; \
        v++; \
    } while (0)
    

夏令时

夏令时会导致很多异常诡异的时间问题。

/* tz-dst.c */
#include <time.h>
#include <stdio.h>

int main( void ) {
    time_t t;
    struct tm temp_tm;
    struct tm tm_out;
    char tmp_time[32];
    
   strptime("2012-10-04 11:12:13", "%Y-%m-%d %H:%M:%S", &temp_tm);      
    t = mktime(&temp_tm);

    localtime_r(&t, &tm_out);
    strftime(tmp_time, 27, "%Y-%m-%d %H:%M:%S", &tm_out);

    printf("%d - %s\n", t, tmp_time);
    return 0;
}

编译执行,再夏令时时区会有问题:

$ gcc tz-dst.c -o dst-test
$ TZ=CST6CET ./dst-test # CST +6 with daylight saving time
1349370733 - 2012-10-04 12:12:13
$ TZ=CST6 ./dst-test # CST +6 without daylight saving time
1349370733 - 2012-10-04 11:12:13

秒数相同,但是转换后时间相差一小时。struct tm结构中tm_isdst可以用于判断当前 是否处于夏时令。localtime(), localtime_r(), mktime()不会参考这个值,而是从 环境变量TZ中获取是否考虑夏令时。

强制mktime()返回UTC时间的方法:

time_t mktime_utc(struct tm * timeinfo) {
    char * tz_old = getenv("TZ");
    time_t ret = 0;

    putenv("TZ=UTC");
    _tzset();

    ret = mktime(timeinfo);
    
    if (!tz_old) {
        setenv("TZ=");
    } else {
        char buf[64];
        sprintf(buf, "TZ=%s", tz_old);
        setenv(buf);
    }
    _tzset();
    return ret;
}