4

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++).

Ofir Hermesh
  • 125
  • 1
  • 1
  • 7

4 Answers4

5

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.

Sergej Zagursky
  • 453
  • 4
  • 16
4

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.

Community
  • 1
  • 1
thkala
  • 84,049
  • 23
  • 157
  • 201
2

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.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
0

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?

Roland Illig
  • 40,703
  • 10
  • 88
  • 121