Let's say for instance I want to use the structure timespec, which is defined in time.h. According to the manpages I only need to include time.h. But when compiling in c99, this isn't enough:
#include <stdio.h>
#include <time.h>
struct timespec abcd;
int main(int argc, char *argv[])
{
return 0;
}
According to the info I find online (not in the manpages), I need to add this:
#define _POSIX_C_SOURCE 200809L
So I have a few questions:
How do I know to which value I need _POSIX_C_SOURCE to be equal? I found multiple values online.
Why does the placement of this definition influence the compilation? (cf . infra)
#include <stdio.h>
#define _POSIX_C_SOURCE 200809L
#include <time.h>
struct timespec abcd;
int main(int argc, char *argv[])
{
return 0;
}
$ gcc test.c -Wall -Wpedantic -std=c99 -o test
test.c:9:25: error: field ‘time_last_package’ has incomplete type
struct timespec time_last_package;
compiles well:
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <time.h>
....
Thanks
How do I know to which value I need _POSIX_C_SOURCE to be equal? I found multiple values online.
There is one value per POSIX standard definition. So you can use any value which:
defines the functionality you need
is supported by your hosting OS
Best is to use the lowest value that meet both those criteria.
Why does the placement of this definition influence the compilation?
POSIX says :
System Interface Chapter 2. Section 2 The Compilation Environment: A POSIX-conforming application should ensure that the feature test
macro _POSIX_C_SOURCE is defined before inclusion of any header.
Otherwise it may leads to wrong/incompatible included definitions... Defining it before any include ensure that all is under the same POSIX version...
Recommended reading : The Open Group Base Specifications Issue 7, 2018 edition, 2 - General Information
The other answer gives nice background. But, it's also possible to define this at the compiler level so you don't have to put it in your source. With gcc and glibc at least, the command-line option
-D_POSIX_C_SOURCE=199309L
is enough to ensure that nanosleep and struct timespec are available if you include <time.h>.
Related
This is my code:
#include <stdio.h>
#include <sys/statfs.h>
int main(int argc, char** argv)
{
struct statfs64 mystatfs64;
statfs64("/", &mystatfs64);
return 0;
}
But I get this error:
error: storage size of ‘mystatfs64’ isn’t known
warning: implicit declaration of function ‘statfs64’; did you mean ‘statfs’?
On the man page it says: The glibc statfs() and fstatfs() wrapper functions transparently deal with the kernel differences.
So I changed my code to:
#include <stdio.h>
#include <sys/statfs.h>
int main(int argc, char** argv)
{
struct statfs mystatfs;
statfs("/", &mystatfs);
return 0;
}
It now compiles but sizeof(((struct statfs*)0)->f_blocks) is 4 so I can't handle big file systems.
I also tried to define __USE_LARGEFILE64 and __USE_FILE_OFFSET64 without any success.
The __USE_* macros are for glibc's internal header features.h to define, not you. If you try to define them yourself, they won't work.
You are instead supposed to define macros from a different set, called the "feature test macros" or "feature selection macros" and partially specified by POSIX. The most up-to-date and coherent documentation of the full set of feature test macros understood by glibc is in the Linux manpages: feature_test_macros(7). Note that most of these macros must be defined before you include any system headers.
The best way to write the code you're trying to write is to use the _FILE_OFFSET_BITS feature test macro to make normal off_t, fsblkcnt_t, etc. be 64 bits wide:
#define _FILE_OFFSET_BITS 64
#include <inttypes.h>
#include <stdio.h>
#include <sys/statfs.h>
int main(int argc, char** argv)
{
struct statfs mystatfs;
statfs("/", &mystatfs);
printf("block count: %"PRIu64"\n", mystatfs.f_blocks);
return 0;
}
If you don't want to add this #define to the top of every .c file of your program, you may instead be able to add -D_FILE_OFFSET_BITS=64 to your compilation options in your Makefile or equivalent (for instance, add it to CPPFLAGS if you're using for Make's standard built-in compilation rules).
You also have the option of using _LARGEFILE64_SOURCE to gain access to the xxx64 functions and types, but this is discouraged by the C library maintainers: note what it says about it in the manpage I linked above
_LARGEFILE64_SOURCEExpose definitions for the alternative API specified by the LFS (Large File Summit) as a "transitional extension" to the Single UNIX Specification. (See ⟨https://www.opengroup.org/platform/lfs.html⟩.) The alternative API consists of a set of new objects (i.e., functions and types) whose names are suffixed with "64" (e.g., off64_t versus off_t, lseek64() versus lseek(), etc.). New programs should not employ this macro; instead _FILE_OFFSET_BITS=64 should be employed.
(boldface: my emphasis)
I am trying include a file constructed from pre-processor macros, but running into a wall due to rules regarding tokens, it seems. I used the answer here as a reference: Concatenate string in C #include filename, but my case differs in that there are decimal points in the define I am using to construct my include. This is what I have currently that will not get through the preprocessor stage:
main.c:
#include <stdio.h>
#include <stdlib.h>
#define VERSION 1.1.0
#define STRINGIFY(arg) #arg
#define INCLUDE_HELPER(arg) STRINGIFY(other_ ##arg.h)
#define INCLUDE_THIS(arg) INCLUDE_HELPER(arg)
#include INCLUDE_THIS(VERSION)
int main(int argc, char **argv) {
printf(INCLUDE_THIS(VERSION));
fflush(stdout);
#if defined (SUCCESS)
printf("\nSUCCESS!\n");
#endif
return EXIT_SUCCESS;
}
other_1.1.0.h:
#define SUCCESS
Were I to use #define VERSION 1_1_0 and renamed the header accordingly it would work (but not viable for my use as I have no control over the name of the header files the actual project uses), but 1.1.0 is not a valid preprocessor token.
EDIT:
After a bit more digging through the documentation, I see that 1.1.0 is a valid preprocessing number; it is the resulting concatenation of other_1.1.0 that is invalid. Regardless, the issue of not being able to construct the include remains.
It's easy once you stop thinking about token concatenation. Stringification works with any sequence of tokens, so there is no need to force its argument into being a single token. You do need an extra indirection so that the argument is expanded, but that's normal.
The only trick is to write the sequence without whitespace, which is what ID is for:
#define STRINGIFY(arg) STRINGIFY_(arg)
#define STRINGIFY_(arg) #arg
#define ID(x) x
#define VERSION 1.1.0
#include STRINGIFY(ID(other_)VERSION.h)
See https://stackoverflow.com/a/32077478/1566221 for a longer explanation.
With some experimentation, I came up with a solution that, while not ideal, could be workable.
#define VERSION _1.1.0
#define STRINGIFY(arg) #arg
#define INCLUDE_HELPER(arg) STRINGIFY(other ##arg.h)
#define INCLUDE_THIS(arg) INCLUDE_HELPER(arg)
#include INCLUDE_THIS(VERSION)
Rather than pasting other_ and 1.1.0 together, I am pasting other and _1.1.0. I am not sure why this is acceptable as the resulting token is the same, but there it is.
I would still prefer to have a solution that allows me to just define the version number without the underscore, so I will hold off on accepting this answer in case someone can come up with a more elegant solution (and works for people who don't happen to need an underscore anyways)
If you are passing -DVERSION=1.1.0 as a compile-line parameter, rather than hard-wiring it in the source code, then there's nothing to stop you passing a second define using make or the shell to do the concatenation. For example, in a makefile, you might have:
VERSION = 1.1.0
VERSION_HEADER = other_${VERSION}.h
CFLAGS += -DVERSION=${VERSION} -DVERSION_HEADER=${VERSION_HEADER}
and then:
#include <stdio.h>
#include <stdlib.h>
#define STRINGIFY(arg) #arg
#define INCLUDE_HELPER(arg) STRINGIFY(arg)
#define INCLUDE_THIS(arg) INCLUDE_HELPER(arg)
#include INCLUDE_THIS(VERSION_HEADER)
int main(void)
{
printf("%s\n", INCLUDE_THIS(VERSION));
#if defined (SUCCESS)
printf("SUCCESS!\n");
#endif
return EXIT_SUCCESS;
}
which is basically your code with the #define VERSION line removed, and using the stringified version of VERSION_HEADER instead of trying to construct the header name in the source code. You might want to use:
#ifndef VERSION
#define VERSION 1.1.0
#endif
#ifndef VERSION_HEADER
#define VERSION_HEADER other_1.1.0.h
#endif
for some suitable default fallback version in case the person running the compilation doesn't specify the information on the command line. Or you might use #error You did not set -DVERSION=x.y.z on the command line instead of setting the default value.
When compiled (source file hdr59.c):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -DVERSION=1.1.0 \
> -DVERSION_HEADER=other_1.1.0.h hdr59.c -o hdr59
$ ./hdr59
1.1.0
SUCCESS!
$
I would put the three lines of macro and the #include line into a separate small header so that it can be included when the version header is needed. If the default setting is required too, then that adds to the importance of putting the code into a separate header for reuse. The program's source code might contain:
#include "other_version.h"
and that header would arrange to include the correct file, more or less as shown.
I'm trying to port some code from windows to linux, but I'm having difficulty with support for large files. off_t seems to be defined when gcc is run with -std=c89 but not for -std=c99. Even a trivial test case will not compile:
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
int main()
{
off_t x = 0;
return 0;
}
It really doesn't seem like this should be difficult (in fact, it's not on all other operating systems). Anyone have any idea what is happening?
The type off_t is not defined by ISO C; it's defined by POSIX.
I get
error: unknown type name ‘off_t’
if I compile with either -std=c90, -std=c99, or -std=c11. That's to be expected, since those options specify conformance to the relevant C standard. Since you're compiling C code that doesn't conform to any of those C standards, you shouldn't use those options.
I find that off_t is defined if I compile with -std=gnu90, -std=gnu99, or -std=gnu11.
Also, off_t is the return type of the lseek function, whose man page on my system says it requires:
#include <sys/types.h>
#include <unistd.h>
You should add those.
I started studying POSIX timers, so I started also doing some exercises, but I immediately had some problems with the compiler.
When compiling this code, I get some strange messages about macros like CLOCK_MONOTONIC. Those are defined in various libraries like time.h etc. but the compiler gives me errors as if they are not defined.
It is strange because I am using a Fedora 16, and some of my friends with Ubuntu get less compiler errors than I :-O
I am compiling with gcc -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -lrt
Here the errors I get:
struct sigevent sigeventStruct gives:
storage size of ‘sigeventStruct’ isn’t known
unused variable ‘sigeventStruct’ [-Wunused-variable]
Type 'sigevent' could not be resolved
unknown type name ‘sigevent’
sigeventStruct.sigev_notify = SIGEV_SIGNAL gives:
‘SIGEV_SIGNAL’ undeclared (first use in this function)
request for member ‘sigev_notify’ in something not a structure or union
Field 'sigev_notify' could not be resolved
if(timer_create(CLOCK_MONOTONIC, sigeventStruct, numero1) == -1) gives:
implicit declaration of function ‘timer_create’ [-Wimplicit-function- declaration]
‘CLOCK_MONOTONIC’ undeclared (first use in this function)
Symbol 'CLOCK_MONOTONIC' could not be resolved
Here is the code:
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
int main()
{
timer_t numero1;
struct sigevent sigeventStruct;
sigeventStruct.sigev_notify = SIGEV_SIGNAL;
if(timer_create(CLOCK_MONOTONIC, sigeventStruct, numero1) == -1)
{
printf( "Errore: %s\n", strerror( errno ) );
}
return 0;
}
Firstly, you can compile your code with -std=gnu99 instead of -std=c99 if you want to have the identifiers SIGEV_SIGNAL, sigeventStruct, and CLOCK_MONOTONIC available.
As noted by #adwoodland these identifiers are declared when _POSIX_C_SOURCE is set to a value >= 199309L, which is the case with -std=gnu99. You can also use -D_POSIX_C_SOURCE=199309L -std=c99 or have the macro defined in source code.
Secondly, see the timer_create prototype, you have to pass pointers as the second and the third argument to the function:
timer_create(CLOCK_MONOTONIC, &sigeventStruct, &numero1)
^ ^
Also you have to include the standard header string.h for strerror function declaration.
If you are using -std=c99 you need to tell gcc you're still using recent versions of POSIX:
#define _POSIX_C_SOURCE 199309L
before any #include, or even with -D on the command line.
Other errors:
Missing #include <string.h>
You need a pointer for timer_create, i.e. &sigeventStruct instead of just sigeventStruct
The other answers suggest _POSIX_C_SOURCE as the enabling macro. That certainly works, but it doesn't necessarily enable everything that is in the Single Unix Specification (SUS). For that, you should set _XOPEN_SOURCE, which also automatically sets _POSIX_C_SOURCE. I have a header I call "posixver.h" which contains:
/*
** Include this file before including system headers. By default, with
** C99 support from the compiler, it requests POSIX 2001 support. With
** C89 support only, it requests POSIX 1997 support. Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/
/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */
#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600 /* SUS v3, POSIX 1003.1 2004 (POSIX 2001 + Corrigenda) */
#else
#define _XOPEN_SOURCE 500 /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */
It is tuned for the systems I work with which don't all recognize the 700 value. If you are working on a relatively modern Linux, I believe you can use 700. It's in a header so that I only have to change one file when I want to alter the rules.
Referring to the CLOCK_MONOTONIC not being defined problem:
As Caterpillar pointed out this is an eclipse bug, more precisely a CDT-Indexer bug with a workaround at eclipse bugs, comment 12
I solved a lot of problems with -std=gnu99 (without specifing any POSIX versions) but I am still having
CLOCK_MONOTONIC could not be resolved
Searching on internet I found some Eclipse bugreports with people complaining about this. Have to check better if is an Eclipse bug, because with
gcc -Wall -w -o Blala timer.c -std=gnu99 -lrt
it compiles
I have a function, createFile that uses fchmod:
int createFile(char *pFileName) {
int ret;
if ((ret = open(pFileName, O_RDWR | O_CREAT | O_TRUNC)) < 0)
errorAndQuit(2);
fchmod(ret, S_IRUSR | S_IWUSR);
return ret;
}
At the top of my file, I have the following includes:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
When compiling: the compiler spits out:
warning: implicit declaration of function ‘fchmod’
I'm including all of the correct files, yet getting this warning. The program runs fine, even with the warning.
By a happy coincidence, your question is directly answered by the feature_test_macros(7) manpage:
Specification of feature test macro requirements in manual pages
When a function requires that a feature test macro is
defined, the manual page SYNOPSIS typically includes a note
of the following form (this example from the chmod(2) manual
page):
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
Feature Test Macro Requirements for glibc (see
feature_test_macros(7)):
fchmod(): _BSD_SOURCE || _XOPEN_SOURCE >= 500
The || means that in order to obtain the declaration of
fchmod(2) from <sys/stat.h>, either of the following macro
definitions must be made before including any header files:
#define _BSD_SOURCE
#define _XOPEN_SOURCE 500 /* or any value > 500 */
Alternatively, equivalent definitions can be included in the
compilation command:
cc -D_BSD_SOURCE
cc -D_XOPEN_SOURCE=500 # Or any value > 500
You didn't specify what compiler or platform you're using, but on my recent Linux installation, fchmod() is defined in but guarded by a couple of #ifdefs (__USD_BSD and __USE_XOPEN_EXTENDED).
You aren't supposed to set those directly, but rather via the _FOO_SOURCE macros in . Try defining _XOPEN_SOURCE_EXTENDED or just _GNU_SOURCE and recompiling (and note that these macros enable nonstandard functionality and use of the functionality they enable may limit the portability of your code).
I have faced this error while building uml.
Just add this line in the file where this error is thrown:
#include "sys/stat.h"
I believe it will take care about adding the macros defined in the above answers.