Why does -std=c11 with gcc hide popen in stdio.h? [duplicate] - c

This question already has answers here:
popen implicitly declared even though #include <stdio.h> is added
(3 answers)
Closed 4 years ago.
I want to use popen. It is in stdio.h. I include that, but the compiler doesn't see it with
-std=c11. It does compile without -std=c11.
#include <stdio.h>
int main(void)
{
popen("ls *","r");
}
gcc -std=c11 popen_test.c
popen_test.c: In function ‘main’:
popen_test.c:5:4: warning: implicit declaration of function ‘popen’ [-Wimplicit-function-declaration]
popen("ls *","r");
^~~~~
It is hidden in stdio.h with
#ifdef __USE_POSIX2
The man page says it is available if:
_POSIX_C_SOURCE >= 2 || /* Glibc versions <= 2.19: */
_BSD_SOURCE || _SVID_SOURCE

popen is not part of C. To get it, you need to enable it with a feature test macro before including anything.
The simplest way to do it is with a #define _GNU_SOURCE at the top (or with -D_GNU_SOURCE in your compiler invocation).
compiles with -std=c11:
#define _GNU_SOURCE
#include <stdio.h>
int main(void)
{
popen("ls *","r");
}

Related

Why I can't reference the implement of function defined in .h file? [duplicate]

This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed last month.
IDE: VS code
gcc version: 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
I new in C , now I have three files:
Get_para.h
#ifndef _GETPARA_H_
#define _GETPARA_H_
extern double C;
extern double dEarthAngularVelocity;
...
extern void calParameter();
#endif
and Get_para.c, which is the implement of Get_para.h
#include <math.h>
#define _USE_MATH_DEFINES
#define pi M_PI
double C = 3e8;
double dEarthAngularVelocity = 7.29210e-5;
...
void calParameter(){
...
}
then, I want to include Get_para.h in test.c and call calParameter function which is implemented in Get_para.c
#include <stdio.h>
#include "Get_para.h"
int main(){
calParameter();
printf("%lf\n",dSemiMajorAxis);
}
I use 'run code' in VS,the command in terminal is:
if ($?) { gcc test.c -o test } ; if ($?) { .\test }
the output is:
C:\Users\bob\AppData\Local\Temp\ccuWLUIl.o:test.c:(.text+0xe): undefined reference to `calParameter'
C:\Users\bob\AppData\Local\Temp\ccuWLUIl.o:test.c:(.rdata$.refptr.dSemiMajorAxis[.refptr.dSemiMajorAxis]+0x0): undefined reference to `dSemiMajorAxis'
collect2.exe: error: ld returned 1 exit status
but I want to just include the "Get_para.h" then I can use the implement of them in "Get_para.c".I search this in google , others' code didn't work on my computer. Now I guess the problem is the parameters of gcc, but can't figure out what is it or what knowledge of C I need to know to solve this problem.
You have to compile the implementation of the function too:
gcc Get_para.c test.c -o test
Consider learning a build system, like cmake.
#define _USE_MATH_DEFINES
For a macro like this to work, it has to be defined before any includes.
#define _USE_MATH_DEFINES
#include <math.h>
#define _GETPARA_H_
It's not valid to define your macros with leading _ followed by an upper case letter. Such identifiers are reserved. For example, use:
#define GETPARA_H_

be64toh not linking or being declared when compiling with -std=c99

When I compile the following program (the code for all the defines I've gotten from 64 bit ntohl() in C++? which seemed sensible):
#include <stdint.h>
#if defined(__linux__)
#include <endian.h> //htobe64,be64toh
#include <arpa/inet.h> //ntohs, ntohl, htonl, htons
#elif defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/endian.h>
#elif defined(__OpenBSD__)
#include <sys/types.h>
#define be16toh(x) betoh16(x)
#define be32toh(x) betoh32(x)
#define be64toh(x) betoh64(x)
#endif
int main()
{
int64_t i = 0x1212121234343434;
int64_t j = be64toh(i);
return 0;
}
I get a linking error when compiling it with the following command (I'm running linux):
gcc -std=c99 endian_test.c -o endian
The error i receive is:
user#host ~/src/c $ gcc -std=c99 derp.c
endian_test.c: In function ‘main’:
endian_test.c:17:2: warning: implicit declaration of function ‘be64toh’ [-Wimplicit-function-declaration]
int64_t j = be64toh(i);
^
/tmp/ccYonfH4.o: In function `main':
endian_test.c:(.text+0x23): undefined reference to `be64toh'
collect2: error: ld returned 1 exit status
Which to me indicates two things, the header itself is included but doesn't really contain the functions/macros needed for this to work and because that means the compiler hopes it's gonna find the function later it tries to go ahead anyway but fails when trying to link.
But if i use the following command to compile (just remove -std=c99):
gcc endian_test.c -o endian
Everything is smooth as butter and works. Any idea why it's happening and what i could do to remedy it? To me it doesn't make sense that functions given by the kernel (or am i mistaken in that fact?) change depending on what standard i use when compiling?
Thanks in advance!
Without explicit -std= option, calling gcc is the same as -std=gnu89 with means C89 + GNU extensions. The GNU extensions will enable macros which will enable the presence of the functions in your header.
If you see the be64toh manual, you will see that it needs the _BSD_SOURCE to be defined. So on Linux #define it before you include <endian.h>.
I had this problem. The solution was to declare not only
#define _BSD_SOURCE
but also
#define __USE_BSD
https://github.com/tailhook/zerogw/pull/34/files#r32008569
Recent changes to glibc has meant you need
#define _DEFAULT_SOURCE
instead of
#define _BSD_SOURCE
Deprecation of _BSD_SOURCE and _SVID_SOURCE feature macros

Using strdup in C11

I am able to compile the following using gcc version 4.7.2
#include <string.h>
int main(){
char text[] = "String duplicate";
char* dup = strdup(text);
return 0;
}
But when I used the --std=c11 flag, I get the following warning:
warning: implicit declaration of function ‘strdup’ [-Wimplicit-function-declaration]
warning: initialization makes pointer from integer without a cast [enabled by default]
What changed to cause this warning?
Read the manual of strdup by
man strdup
You can find that
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
strdup():
_SVID_SOURCE || _BSD_SOURCE || _XOPEN_SOURCE >= 500 || _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED
|| /* Since glibc 2.12: */ _POSIX_C_SOURCE >= 200809L
It denotes that strdup conforms to SVr4, 4.3BSD, POSIX.1-2001.
So you can get rid of the warnings by
gcc -D_BSD_SOURCE -std=c11 <your source file>
I guess the warnings are caused by c11 not enabling one of the above macros.
you want --std=gnu11 or --std=c11 -D_GNU_SOURCE

stdlib.h doesn't have declaration for putenv

I've tried compiling the following code with gcc 4.7.3 and clang 3.2.1 on Ubuntu 13.04 (64-bit):
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main() {
putenv("SDL_VIDEO_CENTERED=1");
return 0;
}
I expected putenv to be declared in the stdlib.h header, but I get the following warning:
test.c: In function ‘main’:
test.c:6:5: warning: implicit declaration of function ‘putenv’ [-Wimplicit-function-declaration]
Why is the declaration for this function missing in my header?
You have to define certain macros. Look at man 3 putenv:
NAME
putenv - change or add an environment variable
SYNOPSIS
#include <stdlib.h>
int putenv(char *string);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
putenv(): _SVID_SOURCE || _XOPEN_SOURCE
Try defining either _SVID_SOURCE or _XOPEN_SOURCE before including stdlib.h, like so:
#define _XOPEN_SOURCE
#include <stdlib.h>
Or when compiling (with -D), like:
gcc -o output file.c -D_XOPEN_SOURCE

getting "implicit declaration of function 'fcloseall' is invalid in C99" when compiling to gnu99

Consider the following C code:
#include <stdio.h>
#include <stdlib.h>
void fatal(const char* message){
/*
Prints a message and terminates the program.
Closes all open i/o streams before exiting.
*/
printf("%s\n", message);
fcloseall();
exit(EXIT_FAILURE);
}
I'm using clang 2.8 to compile: clang -Wall -std=gnu99 -o <executable> <source.c>
And get: implicit declaration of function 'fcloseall' is invalid in C99
Which is true, but i'm explicitly compiling to gnu99 [which should support fcloseall()], and not to c99.
Although the code runs, I don't like to have unresolved warnings when compiling.
How can i solve this?
Edit: corrected tipo.
To include non-standard extensions when you include standard headers you need to define the appropriate feature test macro. In this case _GNU_SOURCE should work.
#define _GNU_SOURCE
#include <stdio.h>
This is independent of -std=gnu99 which enables language extensions, not library extensions.
Here in the man page of fcloseall()
#define _GNU_SOURCE
#include <stdio.h>
You have to define macros _GNU_SOURCE is you snippet, along with stdio.h header. _GNU_SOURCE is a feature test macros which is used to create portable application.

Resources