| Deutsch English Français Italiano |
|
<86msjx6vhr.fsf@linuxsc.com> View for Bookmarking (what is this?) Look up another Usenet article |
Path: ...!2.eu.feeder.erje.net!3.eu.feeder.erje.net!feeder.erje.net!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Tim Rentsch <tr.17687@z991.linuxsc.com>
Newsgroups: comp.lang.c
Subject: Re: how to make a macro work as a single line if stmt without braces
Date: Tue, 24 Sep 2024 06:18:08 -0700
Organization: A noiseless patient Spider
Lines: 74
Message-ID: <86msjx6vhr.fsf@linuxsc.com>
References: <PaWdnZ3R-9zI6nP7nZ2dnZfqn_GdnZ2d@brightview.co.uk> <pan$b0611$9f7137f3$1d714134$ee77076d@invalid.invalid>
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Injection-Date: Tue, 24 Sep 2024 15:18:10 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="601554cda56817d39319d039c1b5e785";
logging-data="3387589"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18ahdx+wLPdSnnFoOXDRoyya6bD9oaBTko="
User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux)
Cancel-Lock: sha1:eT+q/3rFlSJ7T1u4jR5yqQpQM8I=
sha1:XDep7Zxwq62PPh+suN/kihEljhk=
Bytes: 3550
Blue-Maned_Hawk <bluemanedhawk@invalid.invalid> writes:
> Mark Summerfield wrote:
>
>> I have this macro:
>>
>> #define WARN(...) \
>> do { \
>> fprintf(stderr, "%s#%d: ", __FILE__, __LINE__); \
>> fprintf(stderr, __VA_ARGS__); \
>> } while (0);
>>
>> which I use like this:
>>
>> total++;
>> if (failed) {
>> WARN("failed because...");
>> } else
>> ok++;
>>
>> I would prefer to be able to write this instead:
>>
>> total++;
>> if (failed)
>> WARN("failed because...");
>> else
>> ok++;
>>
>> but doing so results in a compiler error:
>>
>> error: 'else' without a previous 'if'
>
> Since the initial problem has already been solved by other messages,
> here's some extra completely unsolicited advice that you are free to
> ignore:
>
> If you intend for this macro to be invoked like how one would
> invoke the printf function (i.e. the arguments consisting of a
> format string literal followed by arguments to be formatted into
> it), you could get away with defining it like this instead:
>
> #define WARN(msg, ...) (fprintf(stderr, "%s#%d: " msg, __FILE__, __LINE__
> __VA_OPT__(,) __VA_ARGS__))
>
> This would break if you try to invoke it with a nonliteral string,
> because this takes advantage of preprocessor adjacent string
> literal concatenation, but modern compilers tend to complain
> mightily if you try that anyway. It would have the advantage of
> expanding to an expression instead, which is often more beneficial
> for macros because it permits more flexibility in placement
> (something that i find unlikely to be relevant for this particular
> one, but which can't really particularly hurt to have anyway).
The alternative below works without needing __VA_OPT__, in earlier
C standards including C90.
#include <stdarg.h>
#include <stdio.h>
#define WARN(...) (warning_with_origin( __FILE__, __LINE__, __VA_ARGS__ ))
int
warning_with_origin( const char *file, long line, const char *format, ... ){
va_list ap;
int a = (va_start( ap, format ), 0);
int b = a < 0 ? a : fprintf( stderr, "%s#%ld: ", file, line );
int c = b < 0 ? b : vfprintf( stderr, format, ap );
int d = c < 0 ? c : fprintf( stderr, "\n" );
return va_end( ap ), d < 0 ? d : a + b + c + d;
}