在可执行文件的哪个段(.BSS,.DATA,其他)中存储了静态变量,以便它们没有名称冲突?例如:
foo.c: bar.c:
static int foo = 1; static int foo = 10;
void fooTest() { void barTest() {
static int bar = 2; static int bar = 20;
foo++; foo++;
bar++; bar++;
printf("%d,%d", foo, bar); printf("%d, %d", foo, bar);
} }
Run Code Online (Sandbox Code Playgroud)
如果我编译两个文件并将其链接到重复调用fooTest()和barTest的main,则printf语句将独立增加.有意义,因为foo和bar变量是翻译单元的本地变量.
但是存储分配在哪里?
需要明确的是,假设您有一个工具链可以输出ELF格式的文件.因此,我相信,有有将一些空间,对于那些静态变量的可执行文件保留.
出于讨论目的,我们假设我们使用GCC工具链.
我试图编写一个宏来检测结构成员是灵活数组还是普通数组。
事实证明,clang 将灵活的数组类型视为不完整(尚未调整大小)的数组类型。
不完整的数组类型可以通过在不同的兼容性测试中与不同的特定大小兼容来检测:
#define ISCOMPWITHARRAYOFN(LVAL,N) _Generic((typeof((LVAL)[0])(*)[N])0, default:0,typeof(&(LVAL)):1)
#define ISINCOMPLETE_ARRAY(LVAL) ( ISCOMPWITHARRAYOFN(LVAL,1) && ISCOMPWITHARRAYOFN(LVAL,2) )
extern char incomplete[];
extern char complete[1];
//accepted by both gcc and clang
_Static_assert(ISINCOMPLETE_ARRAY(incomplete),"");
_Static_assert(!ISINCOMPLETE_ARRAY(complete),"");
Run Code Online (Sandbox Code Playgroud)
这意味着在 clang 上,我可以:
#define ISFLEXIBLE(type,member) ISINCOMPLETE_ARRAY((type){0}.member)
struct flexed{ int a; char m[]; };
struct unflexed0{ int a; char m[1]; };
struct unflexed1{ int a; char m[1]; int b; };
//both GCC and clang accept these:
_Static_assert(!ISFLEXIBLE(struct unflexed0,m),"");
_Static_assert(!ISFLEXIBLE(struct unflexed1,m),"");
//only clang accepts these
_Static_assert(ISFLEXIBLE(struct flexed,m),"");
_Static_assert(ISCOMPWITHARRAYOFN((struct flexed){0}.m,1),"");
_Static_assert(ISCOMPWITHARRAYOFN((struct flexed){0}.m,2),"");
Run Code Online (Sandbox Code Playgroud)
但GCC不接受这一点。
我的问题是 …