asctime 是 C 标准库 <time.h> 中的一个函数,用于将 struct tm 结构体对象转换为一个易读的字符串格式。

函数原型
#include <time.h> char *asctime(const struct tm *timeptr);
功能描述
asctime 函数接收一个指向 struct tm 结构体的指针,该结构体包含了一个被“分解”的时间(年、月、日、时、分、秒等)。asctime 会将这些信息格式化为一个固定的字符串格式。
重要提示:asctime 返回的字符串是一个静态分配的字符数组,这意味着每次调用 asctime,都会覆盖上一次调用返回的结果,你不能同时保存多个由 asctime 生成的字符串,除非你立即将它们复制到另一个缓冲区中。
返回值
函数返回一个指向静态字符数组的指针,该数组的格式如下:
"Wed Jun 30 21:49:08 1993\n\0"
- 格式固定:总是
星期 月份 日 时:分:秒 年\n\0的格式。 - 星期:三个字母的英文缩写(如
Wed,Mon)。 - 月份:三个字母的英文缩写(如
Jun,Dec)。 - 日:两位数的日期(1-31),不足两位前面补空格。
- 时间:
HH:MM:SS格式。 - 年份:四位数年份。
- 换行符和空字符:字符串的末尾总是跟着一个换行符
\n和一个空字符\0。
如果传入的 timeptr 参数是 NULL,函数行为是未定义的(Undefined Behavior)。

参数
timeptr:一个指向 struct tm 结构体的指针,这个结构体通常由以下函数之一填充:
localtime():将time_t时间转换为本地时间的struct tm。gmtime():将time_t时间转换为 UTC(格林威治标准时间)的struct tm。
struct tm 的主要成员如下:
struct tm {
int tm_sec; // 秒,范围 0-59
int tm_min; // 分,范围 0-59
int tm_hour; // 小时,范围 0-23
int tm_mday; // 一月中的第几天,范围 1-31
int tm_mon; // 月份,范围 0-11 (0=一月, 11=十二月)
int tm_year; // 年份,从 1900 年开始的年数,2025年,tm_year = 123
int tm_wday; // 一周中的第几天,范围 0-6 (0=周日, 6=周六)
int tm_yday; // 一年中的第几天,范围 0-365
int tm_isdst; // 夏令时标志,正数表示夏令时,0表示非夏令时,负数表示未知
};
使用示例
下面是一个完整的示例,演示如何获取当前时间,并将其转换为字符串。
#include <stdio.h>
#include <time.h>
int main(void) {
// 1. 获取当前时间的 time_t 值
time_t rawtime;
time(&rawtime);
// 2. 将 time_t 转换为本地时间的 struct tm 结构体
struct tm *timeinfo = localtime(&rawtime);
// 3. 使用 asctime 将 struct tm 转换为字符串
char *time_str = asctime(timeinfo);
// 4. 打印结果
printf("当前时间的 asctime 字符串是:\n");
printf("%s", time_str); // asctime 字符串末尾自带换行符
// 5. 再次调用 asctime,会覆盖上一次的结果
// 为了演示,我们手动修改一下 timeinfo
timeinfo->tm_hour += 1; // 让时间加一小时
time_str = asctime(timeinfo);
printf("\n一小时后的时间是:\n");
printf("%s", time_str);
// 错误示范:不要试图保存多个 asctime 的返回值
// time_t another_time;
// time(&another_time);
// struct tm *another_timeinfo = localtime(&another_time);
// char *str1 = asctime(another_timeinfo);
// sleep(2); // 暂停2秒
// time(&another_time);
// another_timeinfo = localtime(&another_time);
// char *str2 = asctime(another_timeinfo);
// printf("\nstr1: %s", str1); // str1 和 str2 指向的是同一个地方
// printf("str2: %s", str2); // str2 的内容会覆盖 str1
return 0;
}
可能的输出:

当前时间的 asctime 字符串是:
Wed Oct 26 10:30:55 2025
一小时后的时间是:
Wed Oct 26 11:30:55 2025
重要注意事项
-
静态内存:这是
asctime最重要的特性,返回的指针指向一个静态分配的内存区域,这意味着:- 不要释放它:你不能用
free()来释放它,因为它不是malloc或calloc分配的。 - 不要长期保存:如果你在调用
asctime之后又调用了其他可能修改这个静态缓冲区的函数(比如再次调用asctime或ctime),之前保存的指针指向的内容就会失效。 - 线程不安全:在多线程环境中,如果多个线程同时调用
asctime,它们会竞争同一个静态缓冲区,导致数据混乱,在多线程程序中应避免使用asctime。
- 不要释放它:你不能用
-
替代方案: 由于
asctime存在线程不安全和静态缓冲区的问题,现代 C 编程更推荐使用asctime_r(POSIX 标准)或strftime。-
asctime_r:char *asctime_r(const struct tm *timeptr, char *buf);
它是
asctime的可重入版本(reentrant),它需要一个用户提供的缓冲区buf(通常大小为 26 字节),并将格式化后的字符串写入这个缓冲区,然后返回buf的指针,这避免了静态缓冲区的问题,是线程安全的。 -
strftime:size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr);
这是功能最强大、最灵活的格式化时间函数,你可以自定义输出格式,并且它也需要用户提供缓冲区,因此是线程安全的。
char time_str[100]; strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", timeinfo); printf("自定义格式: %s\n", time_str); // 输出: 2025-10-26 10:30:55
-
| 特性 | asctime |
asctime_r |
strftime |
|---|---|---|---|
| 功能 | struct tm -> 固定格式字符串 |
struct tm -> 固定格式字符串 |
struct tm -> 自定义格式字符串 |
| 线程安全 | 不安全 | 安全 | 安全 |
| 内存管理 | 静态缓冲区,无需释放 | 用户提供缓冲区 | 用户提供缓冲区 |
| 灵活性 | 低,格式固定 | 低,格式固定 | 高,可自定义格式 |
| 推荐度 | 不推荐,仅用于兼容旧代码 | 推荐(在 POSIX 环境下) | 强烈推荐,现代 C 程序的首选 |
asctime 是一个简单易用的函数,但由于其固有的缺陷(线程不安全、静态缓冲区),在新的代码中应优先考虑使用 strftime 或 asctime_r。
