Deutsch   English   Français   Italiano  
<87ikobjxed.fsf@nosuchdomain.example.com>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: news.eternal-september.org!eternal-september.org!.POSTED!not-for-mail
From: Keith Thompson <Keith.S.Thompson+u@gmail.com>
Newsgroups: comp.lang.c
Subject: Re: Concatenated if and preprocessor
Date: Fri, 14 Mar 2025 11:10:50 -0700
Organization: None to speak of
Lines: 141
Message-ID: <87ikobjxed.fsf@nosuchdomain.example.com>
References: <vquuhg$34o8d$2@dont-email.me> <vr15ti$rtjs$1@dont-email.me>
MIME-Version: 1.0
Content-Type: text/plain
Injection-Date: Fri, 14 Mar 2025 19:10:54 +0100 (CET)
Injection-Info: dont-email.me; posting-host="bbf3b2da6e551caad2cd296cab2812d3";
	logging-data="1849708"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX19DI93t2kIPasOzXG3THcty"
User-Agent: Gnus/5.13 (Gnus v5.13)
Cancel-Lock: sha1:W1bw3bkE621uLq+wXZActvfMSeo=
	sha1:jY/dLgg5jTSAIHG0nFk7ATXrMTs=

pozz <pozzugno@gmail.com> writes:
> Il 13/03/2025 16:44, pozz ha scritto:
>> Consider this code:
>> if (cond1) {
>> ...
>> } else if (cond2) {
>> ...
>> } else if (cond3) {
>> ...
>> }
>> I want to activate every single if with a macro preprocessor. All
>> the combinations are possible: only the first, only the second, only
>> the third, the first and second... and so on.
>> What's the best method to have a clean code that is always compiled
>> without errors?
>
> You're right, a real example is better to define my problem.
>
> I have a project that can be compiled in different ways, depending on
> the final product model (it's an embedded platform, it's a material
> device).
> I have three models with different characteristics: MODEL_A, MODEL_B,
> MODEL_C. Three different builds that are managed at compile time by
> defining MODEL macro as MODEL_A, MODEL_B or MODEL_C.
>
> For each model, I could have a different features set. FEATURE_1,
> FUTURE_2, FUTURE_3, ...
>
> #if MODEL == MODEL_A
> #  define FEATURE_1   1
> #  define FEATURE_2   0
> #  define FEATURE_3   0
> #elif MODEL == MODEL_B
> #  define FEATURE_1   0
> #  define FEATURE_2   1
> #  define FEATURE_3   0
> #elif MODEL == MODEL_C
> #  define FEATURE_1   1
> #  define FEATURE_2   1
> #  define FEATURE_3   1
> #endif
>
> Now, on the full-featured model (MODEL_C) I could write:
>
> if (key == 1) {
>   ...
> } else if (key == 2) {
>   ...
> } else if (key == 3) {
>   ...
> } else {
>   ...
> }
>
> However, for MODEL_A I should have:
>
> if (key == 1) {
>   ...
> } else {
>   ...
> }
>
> For MODEL_B I should have:
>
> if (key == 2) {
>   ...
> } else {
>   ...
> }
>
> This is the scenario.
> 
> I thought using if(0) or if(1), but many times I receive some warnings
> from the compiler (condition is always true or condition is always
> false).

This indicates something that wasn't expressed in your original post:
that only one of the three runtime conditions can be true.  You might
need to add a dummy "if (0)" at the top of the if/else chain if two
or more of the conditions might be true and the order is significant,
but with the new (pseudo-?)code you've posted that's not necessary.

I'll also note that you've #define'd FEATURE_1 et al as 0 or 1.
I suggest it would be more idiomatic for the FEATURE macros to be
either #define'd or #undef'ed.  (I'm assuming that a feature is
either enabled or disabled, and that there aren't multiple ways
for it to be enabled.)

One way to write it is:

#ifdef FEATURE_1
    if (key == 1) {
        ...
    }
#endif
#ifdef FEATURE_2
    if (key == 2) {
        ...
    }
#endif
#ifdef FEATURE_3
    if (key == 3) {
        ...
    }
#endif

Even if FEATURE_* are all defined, only one of the "..."s will be
executed.

The second and third tests might be redundant if the first
succeeds, but that's trivial and IMHO not worth making the code
more complicated.

Or, assuming it really is a test for the value of an integer "key":

    switch (key) {
    #ifdef FEATURE_1
        case 1:
            ...
            break;
    #endif
    #ifdef FEATURE_2
        case 2:
            ...
            break;
    #endif
    #ifdef FEATURE_2
        case 2:
            ...
            break;
    #endif
    }
    
I'm making some assumptions based on your pseudo-code.  Perhaps in
your real code, the first and second runtime conditions might
both be true and then you want to execute just the first block.
And maybe the logic will need to be changed later.

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */