【问题标题】:How can I add a static assert to check if a variable is static?如何添加静态断言来检查变量是否为静态?
【发布时间】:2011-04-13 07:16:10
【问题描述】:

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

正确:

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

不正确:

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

我使用 GCC for C(非 C++)。

【问题讨论】:

    标签: c static static-assert


    【解决方案1】:

    您可以使用以下技巧:

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

    【讨论】:

    • 谢谢!这真是太好了。但是,当我执行此技巧时,我得到:错误:未使用的变量“p_searchResp”。你知道如何避免这种情况吗?
    • 我想通了:你可以在宏中添加 memcpy(p_ ## v,&v,sizeof(v))
    【解决方案2】:

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

    • .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
    

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

    【讨论】:

    • 好答案!谢谢!但是,这是运行时检查,而不是编译时检查。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-10
        • 1970-01-01
        相关资源
        最近更新 更多