alexandernst
alexandernst

Reputation: 15099

Accessing declared variables inside a #define from another #define

I have this code

struct counter_info {
    atomic_t counter;
    char *name;
} __attribute__((packed));

extern struct counter_info __start_counters;
extern struct counter_info __stop_counters;

#define __DOSOMETHING(F)                                    \
do{                                                         \
    static struct counter_info __counter_info_##F           \
    __attribute((__section__("counters")))                  \
    __attribute((__used__)) = {                             \
        .name = #F,                                         \
    };                                                      \
    atomic_set(&__counter_info_##F.counter, 0);             \
                                                            \
}while(0)

I call this macro as this:

__DOSOMETHING(FOO)

And I'd like to access __counter_info_##F from this other code

#define __DOSOMETHINGELSE(F)                                \
do{                                                         \
    atomic_inc(&__counter_info_##F.counter);            \
}while(0)

with __DOSOMETHINGELSE(FOO)

but I get an undeclared error from the compiler. Why is that? Can it be done?

EDIT:

The exact error is error: ‘__counter_info_FOO’ undeclared (first use in this function) note: in expansion of macro ‘__DOSOMETHINGELSE’

Upvotes: 0

Views: 237

Answers (2)

Mike Housky
Mike Housky

Reputation: 4069

You can't get at that struct from another piece of code because you have declared it inside a braced block. C scope rules prohibit access to code outside that block. That's true even if you get your macro to generate correct name: __counter_info_F instead of __counter_info_FOO.

This isn't a #define issue, by the way. By the time C sees the code, all macro processing is done and the compiler only sees the tokens produced by the preprocessor.

Find a way to get the job done without macros...and THEN figure out a macro representation to ease the coding.

One way would be to use macros that don't use the do loops to seal off those variables. The problem now is to generate unique names. Look carefully at those macros and you'll see that that's the problem that the one-time-loops were created to solve...duplicate names creating double definitions. If you unwrap the macro generated code, you'll have to solve the duplicate name problem in another way...probably by adding macro arguments.

One thing, for the record: You don't need a compound statement like do or for to contain a plain block. Just enclosing in braces is good enough. You can take off the "do" at the beginning and the "while (0);" at the end, and get the same effect.

Upvotes: 4

wildplasser
wildplasser

Reputation: 44250

If the struct is declared static within a function, its visibility will be limited to that function. Example (without macros):

struct hoppa {
        int i;
        };

void start(void)
{
static struct hoppa one = {1};
}

void use_it(void)
{
one.i = 2; //FAIL
}

Upvotes: 0

Related Questions