ideasman42
ideasman42

Reputation: 48068

Declaring variables in macros in C, allowing a trailing semicolon

This is a silly problem with macro declarations, but one I've run into a few times and was curious if there is some solution I'm missing.

I have a macro that declares variables, which I want to ensure are not initialized by mistake.

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 0

Example use:

DECLARE_FOO(var);

however this allows...

DECLARE_FOO(var) + 1;

I could just ignore this (for now Im just leaving it this way), but I'd like to disallow it. simple...

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 0;

However now I have to remove the semicolon from the declaration otherwise I get this warning.

DECLARE_FOO(var);
int bar;

ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]

So, I have to do this...

DECLARE_FOO(var)
int bar;

...which expands correctly, but looks odd for anyone reading the code and not checking the macro definition. Also editors that don't expand macros may warn about this as incorrect syntax.

Is there some way to disallow assignments to the variable but also end usage of the declaration with a semicolon ?

Update

It wasn't really clear in my question, but -Werror=declaration-after-statement infers that C90 is a requirement here, answers mixing in statements wont work in this case since there may be proceeding declarations.

Upvotes: 2

Views: 830

Answers (2)

ideasman42
ideasman42

Reputation: 48068

As long as mixing decelerations and statements is not allowed (C90), then it is not possible to guard against trailing text after the macro.

However it is possible to use ternary operator to ignore the trailing text, this is a fairly poor solution (and I wouldn't recommend its use).

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 1 ? 0 : 0

This won't raise an error, but the + 1 will be ignored.

DECLARE_FOO(var) + 1;

Upvotes: 0

wildplasser
wildplasser

Reputation: 44250

Add a no-op expression to the macro:

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 0; \
    (void) 0

BTW: this will even fail if the macro is used without a semicolon.

UPDATE: another trick: make the last line of the macro an external declaration (which also is a no-op, but will choke without a semicolon)

#define DECLARE_FOO(var) \
    int _##var##_a = 0; \
    int _##var##_b = 0; \
    extern int _##var##_ext

Upvotes: 4

Related Questions