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

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

Related

Why does gcc not complain about htons() but complains about getaddrinfo() when compiled with -std=c99?

The following program compiles and runs fine even if compiled with -std=c99.
#include <stdio.h>
#include <arpa/inet.h>
int main()
{
printf("%d\n", htons(1));
}
Here is the output.
$ gcc -std=c99 foo.c && ./a.out
256
But the following program leads to warning and error.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
int main()
{
struct addrinfo *res;
getaddrinfo("localhost", NULL, NULL, &res);
printf("%d\n", res->ai_flags);
}
Here are the warning and error.
$ gcc -std=c99 bar.c
bar.c: In function ‘main’:
bar.c:9:5: warning: implicit declaration of function ‘getaddrinfo’ [-Wimplicit-function-declaration]
getaddrinfo("localhost", NULL, NULL, &res);
^
bar.c:10:23: error: dereferencing pointer to incomplete type
printf("%d\n", res->ai_flags);
Why does the compiler not complain about htons() but complains about getaddrinfo() when compiled with -std=c99?
I am compiling this code with gcc 4.9.2 on Debian 8.3 system.
From the Linux man pages for glibc:
POSIX.1-2001. htons()
POSIX.1-2001, POSIX.1-2008. The getaddrinfo() function is documented
in RFC 2553.
Since glibc 2.22: _POSIX_C_SOURCE >= 201112L
Glibc 2.21 and earlier: _POSIX_C_SOURCE
To get the prototype for getaddrinfo() you need to specify which version of POSIX you want to use before you include the header, for example:
#define _POSIX_C_SOURCE 201112L
RFC 2553 adds IPv6 support to the socket interface. The addition meant that new structs were added.
Since not all plkatforms implemented the new stuff at once there was a need to specify which version of the interface you need for stuff that had changed. htons is the same in all versions, so it doesn't care what version you request. getaddrinfo has changed due to RFC 2553, so you need to specify that you want/(can handle) the changed version.
As noted in the comments the required value for _POSIX_C_SOURCE varies between platforms. It seems that for gcc on RHEL6 it is sufficient to specify _POSIX_SOURCE or _POSIX_C_SOURCE >= 1.
It would be great if someone could confirm whether _POSIX_SOURCE is a portable way to get the prototype for getaddrinfo on any POSIX system.
The problem is not in getaddrinfo - it is in struct addrinfo. Implicit declaration of gettaddrinfo is a warning, not error. struct addrinfo is not declared and that is the error.
The struct is declared in netdb.h but is hidden under ifdef __USE_POSIX. There is a comment:
/* Extension from POSIX.1g. */
No such ifdef exists for htons.

Why is _GNU_SOURCE macro required for pthread_mutexattr_settype() while it is in POSIX/IEEE standard?

I have written a multithread server program in C, which echoes back all the data that a client sends.
Initially, I used poll() function in my program to detect POLLRDHUP event, for that I defined _GNU_SOURCE macro (This event is defined here).
Later I updated my code & removed poll() function, however I forgot to remove _GNU_SOURCE macro.
Now my code is finally complete (and a little long to post, more than 250 lines). Before removing macro I was compiling my program using:
gcc multi_thread_socket_v4.c -Wall -Werror -g -lpthread -o multi_thread_socket
and it worked fine: No errors, no warnings
After I removed the macro definition, and compiled using same command-line, the output of gcc was:
multi_thread_socket_v4.c: In function ‘main’:
multi_thread_socket_v4.c:194: warning: implicit declaration of function ‘pthread_mutexattr_settype’
multi_thread_socket_v4.c:194: error: ‘PTHREAD_MUTEX_ERRORCHECK’ undeclared (first use in this function)
multi_thread_socket_v4.c:194: error: (Each undeclared identifier is reported only once
multi_thread_socket_v4.c:194: error: for each function it appears in.)
I have included all the required libraries as it worked fine initially.
I peeked into pthread.h at /usr/include/pthread.h and found out this:
/* Mutex types. */
enum
{
PTHREAD_MUTEX_TIMED_NP,
PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_ADAPTIVE_NP
#ifdef __USE_UNIX98
,
PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,
PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
#endif
#ifdef __USE_GNU
/* For compatibility. */
, PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
#endif
};
and this:
#ifdef __USE_UNIX98
/* Return in *KIND the mutex kind attribute in *ATTR. */
extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict
__attr, int *__restrict __kind)
__THROW __nonnull ((1, 2));
/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
PTHREAD_MUTEX_DEFAULT). */
extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
__THROW __nonnull ((1));
I checked out here to check if __USE_UNIX98 is a feature test macro, but it was not there.
So please help me understanding the reasons for the error, because the function & the macro where gcc shows error are defined in POSIX standard. I do not know what more info regarding my problem will be required so please tell me, I will update my question.
You should use
#define _POSIX_C_SOURCE 200112L
if you want to use POSIX features such as pthread_mutexattr_settype ... see http://pubs.opengroup.org/onlinepubs/007904975/functions/xsh_chap02_02.html
Another possibility is
#define _XOPEN_SOURCE 700
See http://man7.org/linux/man-pages/man7/feature_test_macros.7.html and http://pubs.opengroup.org/onlinepubs/9699919799/
Setting _GNU_SOURCE includes POSIX and lots of other definitions.
P.S. I would expect that including <pthread.h> includes <features.h>, which by default defines _POSIX_C_SOURCE as 200112L, but it's possible that you have defined something that overrides that ... see /usr/include/features.h on your system for details of the symbols and their usage.
It doesn't, your problem likely lies elsewhere.
I just compiled a trivial program with the following content:
#include <pthread.h>
int main(int argc, char **argv)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
return 0;
}
This compiles perfectly with gcc -pthread -Wall -Werror a.c.
It's possible that another part of your program causes this, by eg. doing something silly like defining _PTHREAD_H, or some other minor sabotage.
You might want to try to get a minimal test case by using a tool like delta or creduce, which will probably make the problem evident.
When you're using old libraries (e.g. 2.1.x) you should use
#define __USE_UNIX98
Using a macro beginning with "__" it's not usually a good idea, but sometimes it's the only way... see also this discussion

LONG_BIT in limits.h

I'm writing a program for my study and therefore I have to descripe a few wars to get the limits of some data types.
When I'm writing this:
#include <limits.h>
#include <stdio.h>
int main(void)
{
printf("%d\n", CHAR_BIT);
printf("%d\n", LONG_BIT);
return 0;
}
but it gives me the following error:
a.c: In function ‘main’:
a.c:7:17: error: ‘LONG_BIT’ undeclared (first use in this function)
printf("%d\n", LONG_BIT);
^
a.c:7:17: note: each undeclared identifier is reported only once for each function it appears in
even gcc -E gives me this
int main(void)
{
printf("%d\n", 8);
printf("%d\n", LONG_BIT);
return 0;
}
But a grep in limits.h doesn't give me the answer. But bits/xopen_lim.h has this declaration and it should be included when
__USE_XOPEN
is declared, but even a manual declaration won't give me a result.
So where is the problem? A look in the manpage says there is a LONG_BIT macro but gcc says no.
gcc version 4.8.0 (GCC)
OS arch
[edit]
For those who say LONG_BIT is not a c-standard, type
man 0 limits.h
and search for LONG_BIT. For me there are two entries under Numerical Limits and therefore I think LONG_BIT exist.
And no, including bits/xopen_lim.h is not realy an option, because it should be included by limits.h and not manually
Your issue is that you shouldn't be defining __USE_XOPEN. If you take a look at /usr/include/features.h you will see it explicitly undefines it and then redefines these macros based on feature test macros. You probably want to define _XOPEN_SOURCE instead, something like:
gcc -D_XOPEN_SOURCE=700 -o longbit longbit.c
From features.h:
_XOPEN_SOURCE Includes POSIX and XPG things. Set to 500 if
Single Unix conformance is wanted, to 600 for the
sixth revision, to 700 for the seventh revision.
_XOPEN_SOURCE_EXTENDED XPG things and X/Open Unix
extensions.
Also, wrt directly including xopen_lim.h:
/*
* Never include this file directly; use <limits.h> instead.
*/
So, I wouldn't recommend directly including it. Also, see man feature_test_macros or info '(libc)Feature Test Macros'.
LONG_BIT is not a thing in standard C.
For a portable approach, just do this:
CHAR_BIT * sizeof(long)
http://www.cplusplus.com/reference/climits/
There is nothing as such LONG_BIT in limits.h

Constants not loaded by compiler

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

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