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.