3

我有一个宏,它只适用于静态局部变量(因为它使用内联汇编符号来提取有关变量的数据)。我需要一种方法来强制宏的输入确实是静态局部变量:

正确的:

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

不正确:

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

我使用 GCC for C(没有 C++)。

4

4 回答 4

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 对非静态变量发出错误“初始化元素不是常量”。

于 2011-04-15T05:13:10.723 回答
3

您可以通过使用它们的地址来区分静态变量和局部变量:

  • 静态变量存储在 .BSS 或 .DATA 部分中

  • 局部变量存储在堆栈中

例如以下程序在我的系统上的输出

#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

警告:我不建议使用这个“技巧”。就是这样:一个技巧,一个会在最不合时宜的情况下打破的技巧。只需正确记录您的宏,并让使用它的人处理其滥用的后果。

于 2011-04-13T07:30:47.257 回答
2

只需按照大多数 C 库使用的方式进行操作:告诉用户您的宏适用于静态变量,而其他任何东西的行为可能是未定义/意外的。

就像您也可以将 NULL 指针传递给strdup()etc.,这只会导致段错误,不强制执行没有什么大问题。

于 2011-04-13T07:33:24.473 回答
0

我认为您无法在 ISO C 中区分这些情况。但是由于您已经提到使用 GCC,因此可能有一些有用的内置伪函数。它们的名称都以 开头__builtin_,因此您应该通读 GCC 文档中的该列表。

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

好吧,我只是通读了整个内置部分,但没有找到任何东西。所以我认为这真的是不可能的。

出于好奇,您到底想用宏做什么?

于 2011-04-13T07:23:37.330 回答