2011-04-13 114 views
3

我有一個只適用於靜態局部變量的宏(因爲它使用內聯彙編符號來提取有關變量的數據)。我需要一種方法來執行,該輸入宏確實是一個靜態的局部變量:如何添加一個靜態斷言來檢查一個變量是否是靜態的?

正確:

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

不正確:

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

我與海灣合作委員會的工作爲C(無C++)。

回答

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發出一個錯誤「初始元素不是常量」非靜態變量。

+0

謝謝!這真的很好。但是,我得到:錯誤:未使用變量'p_searchResp',當我這樣做的時候。你知道如何拒絕嗎? – 2011-04-20 12:45:07

+0

我想通了:你可以在宏中添加memcpy(p_ ## v,&v,sizeof(v)) – 2011-04-21 06:08:07

0

我認爲你不能在ISO C中區分這些情況。但既然你已經提到你使用GCC,可能會有一些有用的內置僞函數。他們的名字都以__builtin_開頭,所以你應該閱讀GCC文檔中的列表。

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

好吧,我剛剛經歷了全內置插件部分看完了,我沒有發現任何東西。所以我認爲這是不可能的。

無論如何你只是出於好奇而試圖與宏做什麼?

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 

警告:我不會建議使用這個「竅門」。事情完全就是這樣:一種伎倆,一種會在最不合時宜的情況下突破。只要正確記錄你的宏,並讓使用它的人處理濫用的後果。

+0

有趣的答案。 – 2011-04-13 08:39:29

+0

不能保證這一切都會一直有效。 – BiGYaN 2011-04-13 09:26:55

+0

@BiGYaN:因此最後的警告...... – thkala 2011-04-13 09:38:56

2

簡單地以大多數C庫使用的方式來做:告訴用戶你的宏適用於靜態變量,其他任何行爲都可能是未定義的/意外的。

就像你也可以通過NULL指針strdup()等,這將導致沒有什麼,但段錯誤沒有一個大問題,不強制的東西。

相關問題