Path: csiph.com!news.mixmin.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Effect of CPP tags Date: Sun, 31 Dec 2023 16:07:35 -0800 Organization: A noiseless patient Spider Lines: 104 Message-ID: <86bka5uda0.fsf@linuxsc.com> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: dont-email.me; posting-host="4ad5b29cc5222e274263b40ba81c3fd0"; logging-data="1997534"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/ZrdX0/fFg0PhjGZgIrYfNyY37lbG0fjk=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:AruI019hRVodaTSu3/owi48jz5A= sha1:bxR+WLdHorRGD5OCKE+BYUnoyTs= Xref: csiph.com comp.lang.c:379722 Janis Papanagnou writes: > This is a CPP question that arose last month. It's not about an > actual issue with the software, just out of curiosity and to be sure > it works reliable (it seemingly does). > > In a C99 program on Linux (Ubuntu) I intended to use usleep() and > then also strnlen(). > > When I added usleep() and its include file I got an error and was > asked to define the CPP tag '_BSD_SOURCE'. I did so, and because I > wanted side effects of that tag kept as small as possible I > prepended it just before the respective #include and put it at the > end of my #include list > > ...other #includes... > #define _BSD_SOURCE > #include > > But as got obvious *that* way there had been side-effects and I > had to put the tag at the beginning of all include files (which > astonished me) > > #define _BSD_SOURCE > #include > ...other #includes here... > > For the strnlen() function I needed another CPP tag, '_GNU_SOURCE'. > So now I have both CPP tag definitions before the includes I second the recommendations of Lowell Gilbert and others not to define _BSD_SOURCE or _GNU_SOURCE (especially not _GNU_SOURCE) but instead seek alternatives, which are readily available for the two functionalities being sought in this case. > #define _GNU_SOURCE /* necessary for strnlen() in string.h */ > #define _BSD_SOURCE /* necessary for usleep() in unistd.h */ > ...all #includes here... For strnlen(), put an inline definition in a header file: #ifndef HAVE_strnlen_dot_h_header #define HAVE_strnlen_dot_h_header #include static inline size_t strnlen( const char *s, size_t n ){ extern void *memchr( const void *, int, size_t ); const char *p = memchr( s, 0, n ); return p ? (size_t){ p-s } : n; } #include #endif Disclaimer: this code has been compiled but not tested. (If you want you could call this header file "string.h" and do a #include "string.h". I'm not advocating doing that, just pointing it out as an alternative. I expect some people like the idea, and others dislike it, and I don't want to get involved in a style war.) For usleep(), define an alternate function usnooze(), to be used in place of usleep(). In header file usnooze.h: extern int usnooze( unsigned long long ); In source file usnooze.c: #ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 199309L #endif #include "usnooze.h" #include #include int usnooze( unsigned long long snooze_time_in_microseconds ){ typedef unsigned long long ULL; typedef struct timespec TS; ULL seconds = snooze_time_in_microseconds / 1000000; ULL nanoseconds = snooze_time_in_microseconds % 1000000 * 1000; TS need = { .tv_sec = seconds, .tv_nsec = nanoseconds }; TS more; int rc; unsigned most = 1000; while( errno = 0, rc = nanosleep( & need, & more ), rc != 0 ){ if( errno != EINTR || most-- == 0 ) return -1; need = more; } return 0; } The point of putting the definition of usnooze() in a separate file is so the needed #define _POSIX_C_SOURCE doesn't contaminate any more program source than it has to.