Reputation: 145
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
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
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
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
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