有一个时间日期字符串我想转换为tm对象。 Google告诉我,POSIX(但不是C)标准包含一个名为strptime()
的功能,可以完成这项工作。
该手册页说明它位于<time.h>
,我需要在包含#define _XOPEN_SOURCE
文件之前加入<time.h>
。很容易。
但我仍然得到编译器的隐式声明警告。我打开了/usr/include/time.h
并找到了函数声明:
# ifdef __USE_XOPEN
/* Parse S according to FORMAT and store binary time information in TP.
The return value is a pointer to the first unparsed character in S. */
extern char *strptime (const char *__restrict __s,
const char *__restrict __fmt, struct tm *__tp)
__THROW;
#endif
所以看起来我需要#define _USE_XOPEN
。
除此之外也不起作用。编译器仍然没有看到声明。
任何想法。我正在使用相对较新版本的Linux(Mint)和gcc 5.4.0。
答案 0 :(得分:7)
将评论转换为答案。
要解决此问题,您的选项包括在GCC命令行上使用-std=gnu11
代替-std=c11
,或在命令行上使用#define _XOPEN_SOURCE 700
或等效内容(例如-D_XOPEN_SOURCE=700
) 。 700识别POSIX 2008; 600或500标识POSIX或X / Open的早期版本。
理论上,您也可以使用_POSIX_C_SOURCE 200809L
(请参阅POSIX Compilation environment),但这并不会暴露_XOPEN_SOURCE 700
所暴露的所有内容,因此通常最好使用后者。< / p>
请注意,strptime()
的POSIX规范注释为XSI扩展,这意味着您必须设置_XOPEN_SOURCE
;单独设置_POSIX_C_SOURCE
是不够的。
此测试代码打印strptime
函数的地址;如果未声明strptime()
,则无法编译。
#define _XOPEN_SOURCE 700
#include <time.h>
#include <stdio.h>
int main(void)
{
printf("%p\n", (void *)strptime);
return 0;
}
应该使用gcc -std=c11 -Wall -c test-strptime.c
为您编译。如果将-ansi
添加到选项中,则将标准重置为C90。 GCC 5.4.0应该默认为C11(有效-std=gnu11
),除非有人在您正在使用的GCC构建中做了一些可怕的事情(这不太可能)。
请注意,编译器取消设置,然后根据__USE_XOPEN
等设置设置_XOPEN_SOURCE
并尝试手动设置它无法可靠地运行。
您必须在包含第一个系统标头之前指定#define _XOPEN_SOURCE 700
(无论是直接还是间接包含)。如果在尝试设置_XOPEN_SOURCE
之前包含系统标头,则已确定设置,并且有效地忽略后续操作。 POSIX说(在'编译环境'链接已经给出):
在编译
#define
由POSIX.1-2008指定的特征测试宏的应用程序时,在定义特征测试宏之前,不应包括POSIX.1-2008定义的头。此限制也适用于使用这些功能测试宏的任何实现提供的标头。如果宏的定义不在#include
之前,则结果是未定义的。
一个常见的未定义结果是您完全忽略了设置/更改POSIX版本的尝试。