关于C中静态关键字的两个问题

时间:2014-02-24 02:26:23

标签: c static

我有这段代码:

int foo1(void); //line a

int foo2(void) {
    return foo1();
}

int foo1(void) { //line b
    return 99;
}

如果我想声明函数foo1是静态的,我应该将关键字static放在第a行还是第b行?有什么不同吗?

另外说我在上面文件中使用foo1的另一个文件中有以下代码:

static int foo1(void);

int main(void) {
    return foo1();
}

代码仍然编译并按预期工作,尽管我在声明行中放置了静态。但它给出了一个警告说'foo1'已经使用但从未定义 - 如果没有定义,为什么代码仍然有用?

编辑: 对不起,我没说清楚,对于第二个问题,foo1在第一个文件中,它的定义未被声明为静态,但我在第二个文件中将其声明为静态。

3 个答案:

答案 0 :(得分:2)

在第一种情况下,您需要将static放在第a和b行。 C中的静态函数具有内部链接,这意味着它们仅在同一文件中可见。因此,对于声明和定义,您需要放置static以便编译器知道该函数具有内部链接。如果你没有将static放在第一行,你将会遇到一些编译错误。

在第二种情况下,由于foo1是静态函数,因此必须在与main相同的文件中定义它。你只提出一个没有实际定义的前瞻声明。即使它编译得很好,程序也不会链接,因为foo1没有定义。

答案 1 :(得分:1)

此上下文中的static关键字指定不导出foo1,因此特定的foo1只能在同一个编译模块中定义,因此当它不是时会发出警告。 (如果没有static,代码就是正确的,假设您要将foo1与其他文件相关联。)

至于为什么它可以正常工作,我的猜测是编译器依赖于寻找外部函数,它从你的其他文件中找到,但我认为符合标准的编译器在这里给出错误是合理的。

答案 2 :(得分:0)

在C static中,函数意味着内部链接和仅在文件范围内使用该函数。 有趣的是,编译器的行为方式不同

小组1: GCC和clang要求static在声明(行a)中,在定义(行b)中它可以省略。 在MS VC中,您可以将static置于声明或仅在定义中,这使得foo1()成为静态。

Snippet 2(main.c中的静态foo1,其他文件中的非静态声明): GCC编译静态声明而没有定义。 clang编译但是发出警告。 (两者都链接。) MS VS根本不编译第二个片段,给出错误C2129

因此,为了清楚起见,将static放在声明和定义中,并在声明它们的文件中定义静态函数。如果需要,在使用函数之前提出声明。

总的来说,似乎clang具有更好的诊断功能。

“......如果没有定义,为什么代码仍然有效?”

在C语言中,不需要在函数调用之前声明原型。该定义不是在连接步骤中找到的。