C语言声明是否应该与定义匹配,包括关键字和限定符(如"static"、 "inline"等)?

5
考虑以下一个函数声明和定义的例子(在同一翻译单元中):
inline static int foo(int x);

...

int foo(int x)
{
  return x+1;
}

我知道类型需要匹配,但其他关键字和限定符呢?inline static 在两种情况下都需要吗?还是只在声明中需要?
另外,我可以使用 C 标准的哪一部分或者哪些编码规范来证明这个答案呢?
4个回答

2
不,特别是对于inline,它们不应该相同。但这个例子从一开始就是错误的。对于inline,您需要在.h文件中使用定义(整个函数)。通过这样做,您可以避免在包含.h头文件的多个翻译单元(.c)中定义符号。inline只需在一个翻译单元中放置声明而不使用inline来指示应在相应的.o对象文件中生成符号。

@JasonS,如果它只在一个 TU 中,inline 完全没有意义。无论如何,编译器都可以内联每个定义。 - Jens Gustedt
对于我正在使用的这个编译器(Microchip XC16),免费版本的 -O1 优化不会自动内联小函数(但您可以使用 inline 强制执行),而具有 -O2-O3 优化的高级版本则会。但我的问题是普遍的,我正在寻求的建议适用于 clang / gcc / XC16。 - Jason S
1
@JasonS,我明白了。我的建议是,不要因为你有一个优化效果不好的编译器而添加无用的代码。如果你确信这些函数应该被内联,可以使用C模型,在头文件(或者你的.c文件的开头)中使用inline来定义函数,并在稍后的某个地方进行“实例化”,即不带inline的声明。通过这样做,你可以确保代码的可移植性。 - Jens Gustedt
为什么需要实例化 @JensGustedt - user129393192
@user129393192 是的,很有可能 - Jens Gustedt
显示剩余3条评论

1

我希望提供有关内联的详细信息,

你可以很好地分离声明和定义,但该定义必须在使用该函数的每个翻译单元中都可用,即在你的情况下是 inline static int foo(int x);

内联函数包含在ISO C99标准中,但目前GCC实现与ISO C99标准要求之间存在重大差异。

要声明一个内联函数,请在其声明中使用inline关键字,就像这样:

static inline int
inc (int *a)
{
  return (*a)++;
}

内联函数和宏的速度一样快

请注意,函数定义中某些用法可能使其不适合进行内联替换。

请注意,在C语言中,与C++不同,inline关键字不会影响函数的链接。


0
是的,应该包括内联和静态。例如,函数的代码行在声明的.h文件中和定义的.c文件中应该是相同的(所以两种情况都是),但是在主代码文件code.c中调用时,只需要函数名加参数("foo(传递的参数)")。
希望这能帮到你!

1
有什么参考可以证实你所说的话吗?我个人认为我同意你的观点,但我更愿意能够指出C标准或权威风格指南的某个部分。 - Jason S

-1
你只需要在声明中使用inline static,可以在函数定义中省略它。

7.1.1/6:

在命名空间作用域中声明的名称,如果没有存储类说明符,则具有外部链接性,除非它因先前的声明而具有内部链接性,并且只要它没有被声明为const。 声明为const且未显式声明为extern的对象具有内部链接性。

1
不仅如此,对于C语言来说,这样做只会导致错误的方向。在声明中添加“inline”,而在定义中不添加是毫无意义的。 - Jens Gustedt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接