admin管理员组

文章数量:1294384

My code uses nanosleep(). It compiles fine. And now if I try to compile it with -std=c23 flag, nanosleep() isn't recognized.

Any other major C standard version doesn't work. I tried using various versions of _POSIX_C_SOURCE both in code, and compile options, but that too doesn't work.

My code uses nanosleep(). It compiles fine. And now if I try to compile it with -std=c23 flag, nanosleep() isn't recognized.

Any other major C standard version doesn't work. I tried using various versions of _POSIX_C_SOURCE both in code, and compile options, but that too doesn't work.

Share Improve this question edited Feb 12 at 16:45 John Bollinger 182k11 gold badges95 silver badges189 bronze badges asked Feb 12 at 16:01 Programmer_2147483647Programmer_2147483647 1293 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 6

The -std option values calling out a specific standard, i.e. c89, c99, c11, c23, don't include many GNU or POSIX specific functions.

There are alternate values for those standard versions that do include these, i.e. gnu89 gnu99, gnu11, gnu23.

My code uses nanosleep(). It compiles fine. And now if I try to compile it with -std=c23 flag, nanosleep() isn't recognized.

That's to be expected. nanosleep() is not defined by ISO C, and -std=c23 prevents non-ISO functions from being declared by default.

I tried using various versions of _POSIX_C_SOURCE both in code, and compile options, but that too doesn't work.

Apparently you didn't find the right one, or else you didn't apply it correctly. This compiles without warnings for me with -std=c17 (my version of GCC is too old for -std=c23), and works as expected:

#define _POSIX_C_SOURCE 199309L

#include <time.h>

int main(void) {
    nanosleep(&(struct timespec){ .tv_sec = 2 }, NULL);
}

Note well that the definition of _POSIX_C_SOURCE appears at the very top, before any headers are included.

The Linux documentation for nanosleep() told me what value I needed for _POSIX_C_SOURCE. You could also refer to the GCC manual for the feature test macros and values recognized by GCC. If you want C23 conformance and the latest POSIX extensions as of the current GCC and glibc, but not any non-POSIX extensions, then you could define _POSIX_C_SOURCE to 200809L (and continue compiling with -std=c23).

But if you just want C23 syntax and feature support without limiting what library features are available, then the strict-conformance compile modes are counterproductive for you. In that case, you are probably looking for the versioned GNU-source modes, such as -std=gnu23.

POSIX is for the most part not compatible with the C language.

Most notably there's a requirement (ISO 9899:2024 chapter 4) that language extensions available from a conforming compiler + standard lib may not affect the behavior of a "strictly conforming" (ie bare bones) C program.

This is all very clearly and explicitly stated in C23 chapter 4:

A conforming implementation may have extensions (including additional library functions), provided they do not alter the behavior of any strictly conforming program. 1)

1) This implies that a conforming implementation reserves no identifiers other than those explicitly reserved in this document.

In practice that means that language and standard library extensions may definitely not spew external linkage specifiers all over the global namespace when the user includes a standard library header. There are rules for which identifiers that are reserved for the compiler + standard lib (7.1.3) but POSIX has mostly ignored that since day 1. Some things like pthreads are fine, since those come in external libraries of their own. Other things like nanosleep are not OK since it was carelessly dropped into the standard header time.h where it is not allowed.

(There are other minor things like POSIX forbidding _t identifiers, which also collides with standard C, but identifiers in standard headers is by far the biggest design mistake.)

And so when you compile with -std=c23 -pedantic, gcc and others hoping to be conforming C compilers have to strip away all identifiers that POSIX carelessly barfed into the standard headers. If you need POSIX you have to settle for a non-portable compromise like -std=gnu23.

本文标签: cCannot use POSIX functions with std flag with GCCStack Overflow