Reputation: 200
Have a time date string I'd like to convert to a tm object. Google tells me the POSIX (but not the C) standard includes a function called strptime()
that will do the job.
The man page says it's in <time.h>
and that I need to include #define _XOPEN_SOURCE
before I include the <time.h>
file. Easy enough.
But I still get an implicit declaration warning from the compiler. I opened /usr/include/time.h
and found the function declaration:
# 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
So it looks like I need #define _USE_XOPEN
instead.
Except that doesn't work either. The compiler still isn't seeing the declaration.
Any ideas. I'm using a relatively recent version of Linux (Mint) with gcc 5.4.0.
Upvotes: 3
Views: 6505
Reputation: 754540
Converting comments into an answer.
To fix this, your options include using -std=gnu11
instead of -std=c11
on the GCC command line, or using #define _XOPEN_SOURCE 700
or equivalent (e.g. -D_XOPEN_SOURCE=700
on the command line). The 700 identifies POSIX 2008; 600 or 500 identify earlier versions of POSIX or X/Open.
In theory, you could also use _POSIX_C_SOURCE 200809L
(see POSIX Compilation environment), but that doesn't expose everything that _XOPEN_SOURCE 700
exposes so it is usually better to use the latter.
Note that the POSIX specification of strptime()
is annotated as an XSI extension, which means you must set _XOPEN_SOURCE
; setting _POSIX_C_SOURCE
alone is not sufficient.
This test code prints the address of the strptime
function; it won't compile if strptime()
is not declared.
#define _XOPEN_SOURCE 700
#include <time.h>
#include <stdio.h>
int main(void)
{
printf("%p\n", (void *)strptime);
return 0;
}
That should compile for you with gcc -std=c11 -Wall -c test-strptime.c
. If you add -ansi
to the options, you reset the standard back to C90. GCC 5.4.0 should default to C11 (effectively -std=gnu11
) unless someone did something horrible in the build of GCC that you're using (which is unlikely).
Note that the compiler unsets and then sets __USE_XOPEN
based on settings like _XOPEN_SOURCE
and trying to set it manually doesn't work reliably.
You must specify the #define _XOPEN_SOURCE 700
before the first system header is included (whether included directly or indirectly). If you include a system header before trying to set _XOPEN_SOURCE
, the settings have been determined and your subsequent operations are effectively ignored. POSIX says (at the 'compilation environment' link already given):
In the compilation of an application that
#define
s a feature test macro specified by POSIX.1-2008, no header defined by POSIX.1-2008 shall be included prior to the definition of the feature test macro. This restriction also applies to any implementation-provided header in which these feature test macros are used. If the definition of the macro does not precede the#include
, the result is undefined.
One common undefined result is that your attempt to set/change the POSIX version is completely ignored.
Upvotes: 9