gpt4 book ai didi

c - C99 inline 背后的想法是什么?

转载 作者:太空狗 更新时间:2023-10-29 16:55:20 27 4
gpt4 key购买 nike

我对 C99 中的 inline 感到困惑。

这是我想要的:

  1. 我希望我的函数在任何地方都内联,而不仅仅是局限于一个翻译单元(或一个编译单元,一个 .c 文件)。
  2. 我希望函数的地址一致。如果我将函数的地址保存在函数指针中,我希望该函数可从指针调用,并且我不希望在不同的翻译单元中复制相同的函数(基本上,我的意思是没有 static inline )。

C++ inline 正是这样做的。

但是(如果我错了请纠正我)在 C99 中没有办法获得这种行为。

我本可以使用 static inline ,但它会导致重复(同一函数在不同翻译单元中的地址不一样)。我不想要这种重复。

所以,这是我的问题:

  1. C99 中 inline 背后的想法是什么?
  2. 与 C++ 的方法相比,这种设计有什么好处?

引用资料:

  1. 这是一个高度评价 C99 inline 的链接,但我不明白为什么。这种“只在一个编译单元中”的限制真的那么好吗?
    http://gustedt.wordpress.com/2010/11/29/myth-and-reality-about-inline-in-c99/
  2. 这是 C99 inline 的基本原理。看过了,没看懂。
    Is "inline" without "static" or "extern" ever useful in C99?
  3. 一篇不错的帖子,提供了使用 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() 中。

实际上,这与引用 1 和引用 3 给出的指令完全相同。我怎么了?

我用了一个太旧版本的GCC (3.4.5) 来实验,它给了我“multiple definition of 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 所说明的内容。 (在那个例子中,外部可见性通过在之后声明函数 extern 追溯应用于 inline 定义:这个声明可以在 .c.h 文件中定义之后的文件,这颠覆了通常的用法。)

如果内联可以在任何地方完成,你就不需要 extern 函数了。但是,在递归和引用函数地址等上下文中使用非内联调用。从某种意义上说,您可能会通过省略 extern 部分来获得“始终内联”的语义,但是对于任何简单的函数调用,这可能会任意失败,因为标准并不要求内联调用只是因为有是别无选择。 (这是 linked question 的主题。)

C++ 使用“模糊链接”的实现概念来处理这个问题;这在标准中没有指定,但在编译器内部是非常真实且棘手的。 C 编译器应该比 C++ 更容易编写;我相信这可以解释语言之间的差异。

关于c - C99 inline 背后的想法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23272985/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com