我对C99中的inline
感到困惑。
这是我想要的:
.c
文件)。 static inline
)。 C++
inline
正是这样做的。但是(如果我错了,请纠正我)在C99中无法实现此行为。
我可以使用
static inline
,但是会导致重复(同一函数在不同翻译单元中的地址不同)。我不要这个重复。所以,这是我的问题:
inline
背后的想法是什么? 引用:
inline
的链接,但我不明白为什么。这个“仅在一个编译单元中”的限制真的那么好吗? http://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/ inline
的基本原理。我已经读过,但是我听不懂。 Is "inline" without "static" or "extern" ever useful in C99? inline
函数的策略。 http://www.greenend.org.uk/rjk/tech/inline.html 答案摘要
如何在C99中获得C++
inline
行为(是的,我们可以)head.h
#ifndef __HEAD_H__
#define __HEAD_H__
inline int my_max(int x, int y) {
return (x>y) ? (x) : (y);
}
void call_and_print_addr();
#endif
src.c
#include "head.h"
#include <stdio.h>
// This is necessary! And it should occurs and only occurs in one [.c] file
extern inline int my_max(int x, int y);
void call_and_print_addr() {
printf("%d %u\n", my_max(10, 100), (unsigned int)my_max);
}
main.c
#include <stdio.h>
#include "head.h"
int main() {
printf("%d %u\n", my_max(10, 100), (unsigned int)my_max);
call_and_print_addr();
return 0;
}
编译:
gcc -O3 main.c src.c -std=c99
使用以下命令检查程序集:gcc -O3 -S main.c src.c -std=c99
,您会发现my_max
和call_and_print_addr()
都内联了main()
。实际上,这与ref 1和ref 3给出的指令完全相同。我怎么了?
我使用的是GCC (3.4.5)的版本过旧,它给出了“
my_max
的多个定义”错误消息,这是我如此困惑的真正原因。耻辱。C99和C++
inline
之间的区别实际上,您可以通过
g++
编译上面的示例:g++ main.c src.c
extern inline int my_max(int x, int y);
在C++中是多余的,但在C99中是必需的。
那么在C99中它做什么呢?
同样,使用
gcc -O3 -S main.c src.c -std=c99
,您将在src.s
中找到类似的内容:_my_max:
movl 4(%esp), %eax
movl 8(%esp), %edx
cmpl %eax, %edx
cmovge %edx, %eax
ret
.section .rdata,"dr"
如果剪切
extern inline int my_max(int x, int y);
并将其粘贴到main.c
中,则会在main.s
中找到这些汇编代码。因此,通过
extern inline
,您告诉编译器将在何处定义和编译真正的函数my_max()
,您可以通过其地址来调用它。现在回头看一下C++,我们无法指定它。我们永远不会知道
my_max()
会在哪里,这就是@Potatoswatter的“模糊链接”。正如@Adriano所说,大多数时候,我们并不关心这个细节,但是C99确实消除了歧义。
最佳答案
要获得类似C++的行为,您需要为每个TU赋予可能内联的调用inline
定义,并为一个TU提供一个外部可见的定义。这正是C标准相关部分(功能说明符)中的示例1所说明的内容。 (在该示例中,通过在之后声明inline
函数将外部可见性追溯到extern
定义:可以在.c
文件中的定义之后在.h
文件中进行此声明,这使通常的用法成为现实。)
如果内联几乎可以在任何地方完成,则不需要extern
函数。但是,在诸如递归和引用函数地址的上下文中使用非内联调用。从某种意义上讲,您可以通过省略extern
部分来获得“始终内联”的语义,但是对于任何简单的函数调用,这可能会任意失败,因为该标准并不仅仅因为没有其他选择而要求内联该调用。 (这是linked question的主题。)
C++通过“模糊链接”的实现概念来解决这个问题。这个在标准中没有指定,但是在编译器内部是非常真实且棘手的。 C编译器应该比C++更容易编写;我相信这可以解释两种语言之间的差异。
关于c - C99内联背后的想法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23272985/