time_t t1 = time(NULL); sleep(3); time_t t2 = time(NULL);
struct tm *tm1 = localtime(&t1);
struct tm *tm2 = localtime(&t2);
struct tm *tm3 = localtime(&t1); // 本意獲取 t1 時間
printf("tm1=%p tm2=%p tm3=%p\n", tm1, tm2, tm3); // 三者地址相同!
printf("%s", asctime(tm1)); // 輸出 t2 時間
printf("%s", asctime(tm2)); // 輸出 t2 時間
printf("%s", asctime(tm3)); // 輸出 t2 時間
localtime 使用靜態內部 struct tm每次調用覆蓋同一塊靜態內存,返回同一地址。後續調用 asctime 時傳入的均為最新值指針。
struct tm tm4 = *localtime(&t1); // 解引用拷貝
struct tm tm5 = *localtime(&t2);
printf("tm4=%p tm5=%p\n", &tm4, &tm5); // 不同地址
printf("tm4.sec=%d tm5.sec=%d\n", tm4.tm_sec, tm5.tm_sec); // 正確秒數
asctime 也用靜態字符數組printf("%s%s", asctime(&tm4), asctime(&tm5)); // 連續調用
// 第一參數 asctime(&tm4) 更新靜態緩衝區為 tm4 時間
// 第二參數 asctime(&tm5) 覆蓋為 tm5 時間
// printf 讀取兩個參數時,緩衝區已是 tm5 時間 → 兩次輸出相同
正確做法:調用後立即使用/拷貝
printf("%s", asctime(&tm4)); // 立即輸出 tm4
printf("%s", asctime(&tm5)); // 立即輸出 tm5
// 或拷貝到本地字符數組
char buf1[26], buf2[26];
strcpy(buf1, asctime(&tm4));
strcpy(buf2, asctime(&tm5));
| 函數 | 返回類型 | 風險 |
|---|---|---|
| localtime | struct tm * | 靜態結構體被覆蓋 |
| gmtime | struct tm * | 同上 |
| asctime | char * | 靜態字符數組被覆蓋 |
| ctime | char * | 同上 |
localtime_r/gmtime_r/asctime_r/ctime_r 可重入版本