zsh*_*zsh 9 c c99 extern inline-functions
我inline在C99 感到困惑.
这就是我想要的:
.c文件).static inline).C++就是inline这样做的.
但是(如果我错了请纠正我)在C99中没有办法得到这种行为.
我可以使用static inline,但它会导致重复(不同翻译单元中相同功能的地址不一样).我不希望这种重复.
所以,这是我的问题:
inlineC99的理念是什么?参考文献:
inline,但我不明白为什么.这只"仅在一个编译单元中"限制真的那么好吗?inline.我读过它,但我不明白.inline函数的策略.inline在C99中获得C++ 行为(是的,我们可以)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
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
与编译:gcc -O3 main.c src.c -std=c99
检查装配有:gcc -O3 -S main.c src.c -std=c99,你会发现,my_max在两个内联call_and_print_addr()和main().
实际上,这与参考文献1和参考文献3给出的说明完全相同.我有什么问题?
我用了太旧版本的GCC(3.4.5)进行实验,它给了我my_max"错误信息的多重定义",这就是为什么我这么困惑的真正原因.耻辱.
inline实际上你可以通过g++以下方式编译上面的例子: g++ main.c src.c
extern inline int my_max(int x, int y);
Run Code Online (Sandbox Code Playgroud)
在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"
Run Code Online (Sandbox Code Playgroud)
如果你剪切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部分来获得"始终内联"语义,但是对于任何简单的函数调用,这可能会随意失败,因为标准并不要求仅仅因为没有替代方案而内联调用.(这是相关问题的主题.)
C++使用"模糊链接"的实现概念来处理这个问题; 这在标准中没有规定,但在编译器中是非常真实的,也很棘手.C编译器应该比C++更容易编写; 我相信这解释了语言之间的差异.