Ofir Hermesh
Ofir Hermesh

Reputation: 145

How can I add a static assert to check if a variable is static?

I have a macro which works well only on static local variables (since it uses inline assembly notation to extract data about the variable). I need a way to enforce that the input to the macro is indeed a static local variable:

correct:

func f()
{
    static int x;
    my_macro(x);
}

not correct:

func f()
{
    int x;
    my_macro(x);
}

I work with GCC for C (no C++).

Upvotes: 4

Views: 1206

Answers (4)

Sergej Zagursky
Sergej Zagursky

Reputation: 453

You can use following trick:

#define ASSERT_LOCAL_STATIC(v) static void *p_ ## v = &v

void fn()
{
    int nonstatic_var = 0;
    static int static_var = 0;

    ASSERT_LOCAL_STATIC(static_var);
    ASSERT_LOCAL_STATIC(nonstatic_var);
}

GCC issues an error "initializer element is not constant" for non-static variables.

Upvotes: 5

thkala
thkala

Reputation: 86343

You might be able to tell static and local variables apart by using their addresses:

  • Static variables are stored in either the .BSS or .DATA sections

  • Local variables are stored in the stack

For example the output of the following program on my system

#include <stdio.h>

void f0() {
    int x = 0;
    printf("%p\n", &x);
}

void f1() {
    static int x = 0;
    printf("%p\n", &x);
}

int main() {
        f0();
        f1();

        return 0;
}

is this:

0x7fff1dc718dc
0x600900

Where each section and the stack are placed depends on the ABI of your platform, but you could use the address of a block-local variable to form a condition:

#include <stdio.h>

#define check(var) { \
        int ___ = 0; \
        printf("%s (%p): %s\n", #var, &var, (&var > &___)?"local":"static"); \
}

void f0() {
    int x = 0;
    check(x);
}

void f1() {
    static int y = 0;
    check(y);
}

int main() {
        f0();
        f1();

        return 0;
}

This outputs:

x (0x7fff4b965afc): local
y (0x600978): static

Warning: I would not advise using this "trick". That's all it is: a trick, one that will break in the most unopportune of circumstances. Just document your macro properly and let the people who use it handle the aftermath of its misuse.

Upvotes: 4

Roland Illig
Roland Illig

Reputation: 41625

I think you cannot distinguish these cases in ISO C. But since you already mentioned that you use GCC there may be some helpful built-in pseudo functions. Their names all start with __builtin_, so you should read through that list in the GCC documentation.

http://www.google.com/search?q=gcc+builtin

Well, I just read through the whole built-ins section, and I didn't find anything. So I think it is really not possible.

What are you trying to do anyway with the macro, just out of curiosity?

Upvotes: 0

ThiefMaster
ThiefMaster

Reputation: 318518

Simply do it in the way most C libraries use: Tell users that your macro works for static variables and the behavior for anything else may be undefined/unexpected.

Just like you can also pass NULL pointers to strdup() etc. which will result in nothing but a segfault there's not a big issue with not enforcing stuff.

Upvotes: 2

Related Questions