How can I add a static assert to check if a variable is static?
I have a macro which works well o开发者_JS百科nly 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++).
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.
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.
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.
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?
精彩评论