【发布时间】:2014-06-09 23:30:31
【问题描述】:
我对 C99 中的 inline 感到困惑。
这就是我想要的:
- 我希望我的函数在任何地方都能内联,而不仅仅局限于一个翻译单元(或一个编译单元,
.c文件)。 - 我希望函数的地址一致。如果我将函数的地址保存在函数指针中,我希望函数可以从指针调用,并且我不希望在不同的翻译单元中重复相同的函数(基本上,我的意思是没有
static inline)。李>
C++ inline 正是这样做的。
但是(如果我错了,请纠正我)在 C99 中没有办法得到这种行为。
我可以使用static inline,但它会导致重复(不同翻译单元中相同函数的地址不一样)。我不想要这种重复。
所以,这是我的问题:
- C99 中
inline背后的想法是什么? - 与 C++ 的方法相比,这种设计有什么好处?
参考资料:
- 这是一个高度评价 C99
inline的链接,但我不明白为什么。这种“仅在一个编译单元中”的限制真的那么好吗?
http://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/ - 这是 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 确实消除了歧义。
【问题讨论】:
-
你不能“到处内联”,例如,如果函数递归,或者正如你提到的,它是通过指针调用的,会发生什么?
-
这个问题可以通过删除乱七八糟的部分来改善。
-
“复制真的让我很不舒服”。那你为什么要使用内联?向您的编译器提出这样的建议,您可以免费(并且乐意)生成大量重复的代码......
-
@Simon 对不起,我学习英语作为第二语言。我没有试图生气,但也许不知何故它看起来很冒犯。还有 Oliver Matthews,感谢您编辑这篇文章。
-
@Alex “不可能在任何地方都内联函数同时拥有唯一的地址。”。 C++ 标准明确要求
inline函数具有唯一地址,并且实现没有问题。 (函数不是内联的,函数调用是;函数调用,内联或其他,没有地址,但函数有)。
标签: c c99 extern inline-functions