我有一个宏只适用于静态局部变量(因为它使用内联汇编表示法来提取有关变量的数据)。我需要一种方法来强制宏的输入确实是一个静态局部变量:
正确的:
func f()
{
static int x;
my_macro(x);
}
不正确:
func f()
{
int x;
my_macro(x);
}
我使用GCC for C(没有C ++)。
答案 0 :(得分:4)
您可以使用以下技巧:
#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为非静态变量发出错误“初始化元素不是常量”。
答案 1 :(得分:3)
您可以通过使用地址来区分静态和局部变量:
.BSS或.DATA部分中的静态变量为stored
局部变量存储在堆栈中
例如我系统上以下程序的输出
#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;
}
就是这样:
0x7fff1dc718dc
0x600900
其中每个部分和堆栈的放置取决于您的平台的ABI,但您可以使用块局部变量的地址来形成条件:
#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;
}
输出:
x (0x7fff4b965afc): local
y (0x600978): static
警告:我不建议使用这个“技巧”。这就是全部:一个技巧,一个将在最不合时宜的情况下打破的技巧。只需正确记录您的宏,并让使用它的人处理其滥用的后果。
答案 2 :(得分:2)
简单地按照大多数C库使用的方式执行:告诉用户您的宏适用于静态变量,而其他任何内容的行为都可能是未定义/意外的。
就像你也可以将NULL指针传递给strdup()
等等,除了段错误之外什么都没有,没有强制执行内容的大问题。
答案 3 :(得分:0)
我认为您无法在ISO C中区分这些情况。但由于您已经提到使用GCC,因此可能会有一些有用的内置伪函数。他们的名字都以__builtin_
开头,因此您应该在GCC文档中阅读该列表。
http://www.google.com/search?q=gcc+builtin
好吧,我刚刚阅读了整个内置插件部分,但我没有找到任何内容。所以我认为这是不可能的。
出于好奇心,你还想用宏来做什么?