“静态”和“静态”有什么区别?和“静态内联”功能?

发布于 2024-12-09 12:34:58 字数 124 浏览 0 评论 0原文

IMO 都使函数仅具有翻译单元的范围。

“静态”和“静态内联”函数有什么区别?

为什么应该将 inline 放在头文件中,而不是放在 .c 文件中?

IMO both make the function to have a scope of the translation unit only.

What's the difference between "static" and "static inline" function?

Why should inline be put in a header file, not in .c file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

佼人 2024-12-16 12:34:58

默认情况下,内联定义仅在当前翻译单元中有效。

如果存储类是extern,则标识符具有外部链接,并且内联定义也提供外部定义。

如果存储类是静态的,则标识符具有内部链接,并且内联定义在其他翻译单元中不可见。

如果未指定存储类,则内联定义仅在当前翻译单元中可见,但标识符仍然具有外部链接,并且必须在不同的翻译单元中提供外部定义。如果在当前翻译单元内调用该函数,则编译器可以自由使用内联定义或外部定义。

由于编译器可以自由内联(和不内联)其定义在当前翻译单元中可见的任何函数(并且,由于链接时优化,即使在不同的翻译单元中,尽管 C 标准并没有真正考虑到),对于大多数实际目的,staticstatic inline 函数定义之间没有区别。

inline 说明符(如 register 存储类)只是编译器提示,编译器可以完全忽略它。符合标准的非优化编译器只需考虑其副作用,而优化编译器将在有或没有显式提示的情况下进行这些优化。

不过,inlineregister 并不是无用的,因为它们会指示编译器在程序员编写导致无法进行优化的代码时抛出错误:外部 inline< /code> 定义不能引用具有内部链接的标识符(因为这些标识符在不同的翻译单元中不可用)或定义具有静态存储持续时间的可修改局部变量(因为它们不会跨翻译单元共享状态),并且您可以' t 取地址注册限定变量。

就我个人而言,我使用约定将标头中的静态函数定义标记为内联,因为将函数定义放入头文件中的主要原因是使它们可内联。

一般来说,除了标头中的 extern 声明之外,我只使用 static inline 函数和 static const 对象定义。

我从未编写过存储类与static 不同的内联 函数。

By default, an inline definition is only valid in the current translation unit.

If the storage class is extern, the identifier has external linkage and the inline definition also provides the external definition.

If the storage class is static, the identifier has internal linkage and the inline definition is invisible in other translation units.

If the storage class is unspecified, the inline definition is only visible in the current translation unit, but the identifier still has external linkage and an external definition must be provided in a different translation unit. The compiler is free to use either the inline or the external definition if the function is called within the current translation unit.

As the compiler is free to inline (and to not inline) any function whose definition is visible in the current translation unit (and, thanks to link-time optimizations, even in different translation units, though the C standard doesn't really account for that), for most practical purposes, there's no difference between static and static inline function definitions.

The inline specifier (like the register storage class) is only a compiler hint, and the compiler is free to completely ignore it. Standards-compliant non-optimizing compilers only have to honor their side-effects, and optimizing compilers will do these optimizations with or without explicit hints.

inline and register are not useless, though, as they instruct the compiler to throw errors when the programmer writes code that would make the optimizations impossible: An external inline definition can't reference identifiers with internal linkage (as these would be unavailable in a different translation unit) or define modifiable local variables with static storage duration (as these wouldn't share state accross translation units), and you can't take addresses of register-qualified variables.

Personally, I use the convention to mark static function definitions within headers also inline, as the main reason for putting function definitions in header files is to make them inlinable.

In general, I only use static inline function and static const object definitions in addition to extern declarations within headers.

I've never written an inline function with a storage class different from static.

只等公子 2024-12-16 12:34:58

inline 指示编译器尝试将函数内容嵌入到调用代码中,而不是执行实际的调用。

对于频繁调用的小函数,可以产生很大的性能差异。

然而,这只是一个“提示”,编译器可能会忽略它,并且即使不使用关键字,大多数编译器也会尝试“内联”,作为优化的一部分(如果可能)。

例如:

static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};

这个紧密循环将在每次迭代时执行一次函数调用,而函数内容实际上明显少于编译器执行调用所需的代码。 inline 本质上会指示编译器将上面的代码转换为等效的代码:

 int i;
 ....
 for (i=0; i<999999; i = i+1) { /* do something here */};

跳过实际的函数调用并返回

显然,这是一个说明要点的示例,而不是真正的代码段。

static 指的是范围。在 C 中,这意味着函数/变量只能在同一翻译单元内使用。

inline instructs the compiler to attempt to embed the function content into the calling code instead of executing an actual call.

For small functions that are called frequently that can make a big performance difference.

However, this is only a "hint", and the compiler may ignore it, and most compilers will try to "inline" even when the keyword is not used, as part of the optimizations, where its possible.

for example:

static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};

This tight loop will perform a function call on each iteration, and the function content is actually significantly less than the code the compiler needs to put to perform the call. inline will essentially instruct the compiler to convert the code above into an equivalent of:

 int i;
 ....
 for (i=0; i<999999; i = i+1) { /* do something here */};

Skipping the actual function call and return

Obviously this is an example to show the point, not a real piece of code.

static refers to the scope. In C it means that the function/variable can only be used within the same translation unit.

勿挽旧人 2024-12-16 12:34:58

根据我使用 GCC 的经验,我知道 staticstatic inline 在编译器发出有关未使用函数的警告方面有所不同。更准确地说,当您声明static函数并且当前翻译单元中未使用该函数时,编译器会生成有关未使用函数的警告,但您可以通过将其更改为static inline。

因此,我倾向于认为 static 应该在翻译单元中使用,并受益于编译器进行额外检查以查找未使用的函数。并且应该在头文件中使用static inline来提供可以内联的函数(由于缺乏外部链接)而不发出警告。

不幸的是我找不到这种逻辑的任何证据。即使从 GCC 文档中我也无法得出结论:内联会禁止未使用的函数警告。如果有人能分享相关描述的链接,我将不胜感激。

From my experience with GCC I know that static and static inline differs in a way how compiler issue warnings about unused functions. More precisely when you declare static function and it isn't used in current translation unit then compiler produce warning about unused function, but you can inhibit that warning with changing it to static inline.

Thus I tend to think that static should be used in translation units and benefit from extra check compiler does to find unused functions. And static inline should be used in header files to provide functions that can be in-lined (due to absence of external linkage) without issuing warnings.

Unfortunately I cannot find any evidence for that logic. Even from GCC documentation I wasn't able to conclude that inline inhibits unused function warnings. I'd appreciate if someone will share links to description of that.

孤者何惧 2024-12-16 12:34:58

一个区别不是语言级别的,而是流行的实现级别的:某些版本的 gcc 会默认从输出中删除未引用的 static inline 函数,但会保留普通的 static 函数如果未引用。我不确定这适用于哪些版本,但从实际角度来看,这意味着始终对标头中的 static 函数使用 inline 可能是个好主意。

One difference that's not at the language level but the popular implementation level: certain versions of gcc will remove unreferenced static inline functions from output by default, but will keep plain static functions even if unreferenced. I'm not sure which versions this applies to, but from a practical standpoint it means it may be a good idea to always use inline for static functions in headers.

[旋木] 2024-12-16 12:34:58

在C中,static表示您定义的函数或变量只能在本文件(即编译单元)中使用,

因此,static inline表示可以使用的内联函数仅在此文件中。

编辑:

编译单元应该是翻译单元

In C, static means the function or variable you define can be only used in this file(i.e. the compile unit)

So, static inline means the inline function which can be used in this file only.

EDIT:

The compile unit should be The Translation Unit

纸伞微斜 2024-12-16 12:34:58

在 C++ 中,inline 的一个重要作用(即我认为其他答案中尚未提及)是,当找到函数的多个定义时,它可以防止链接器错误。

考虑在头文件中定义的函数,以允许将其内联到包含头文件的源文件中。如果编译器决定内联(所有调用)此函数,函数定义将包含在引用它的每个对象文件中(即不内联所有调用)。

这可能会导致函数的多个定义读取链接器(尽管并非总是如此,因为它取决于编译器做出的内联决策)。如果没有 inline 关键字,这会产生链接器错误,但是 inline 关键字告诉链接器只选择一个定义并丢弃其余的定义(预计它们是相等的,但是此项未检查)。

另一方面,static 关键字可确保如果某个函数包含在目标文件中,则该函数对于该目标文件来说将是私有的。如果多个目标文件包含相同的函数,它们将共存,并且对该函数的所有调用都将使用它们“自己的”版本。这意味着占用更多内存。实际上,我认为这意味着对头文件中定义的函数使用静态并不是一个好主意,最好只使用内联。

实际上,这也意味着static函数不能产生链接器错误,因此上面inline的效果对于static函数来说并不是真正有用。但是,正如 另一个答案中的任何内容所建议的,添加 inline 可能有助于防止警告未使用的功能。

请注意,上述情况对于 C++ 来说是正确的。在 C 中,内联 工作方式有点不同,并且您必须在单个源文件中显式放置 extern 声明,才能将内联函数发送到该对象文件中,以便它可用于任何非内联用途。换句话说,inline 意味着函数不会发送到任何源文件中,即使并非所有调用都是内联的,除非它也被指定为 extern,然后它被发出(即使所有本地调用都是内联的)。不过,我不确定它如何与 static 交互。

In C++, one important effect of inline (that is not mentioned in the other answers yet, I think) is that it prevents linker errors when multiple definitions of the function are found.

Consider a function that is defined in a header file to allow it to be inlined into the source files that include the header. If the compiler decides to not inline (all calls to) this function, the function definition will be included into every object file that references it (i.e. does not inline all calls).

This might cause multiple definitions of the functions to read the linker (though not always, since it depends on the inlining decisions made by the compiler). Without the inline keyword, this produces a linker error, but the inline keyword tells the linker to just pick one definition and discard the rest (which are expected to be equal, but this is not checked).

The static keyword, on the other hand, ensures that if a function is included in the object file, it will be private to that object file. If multiple object files contain the same function, they will coexist and all calls to the function will use their "own" version. This means that more memory is taken up. In practice, I believe this means that using static for functions defined in header files is not a good idea, better to just use inline.

In practice, this also means that static functions cannot produce linker errors, so the effect of inline above is not really useful for static functions. However, as suggested by ony in another answer, adding inline might be helpful to prevent warnings for unused functions.

Note that the above is true for C++. In C, inline works a bit different, and you have to explicitly put an extern declaration in a single source file to have the inline function emitted into that object file so it is available for any non-inlined uses. In other words, inline means that a function is not emitted into any source file, even when not all calls are inlined, unless it is also specified as extern, and then it is emitted (even if all local calls are inlined). I'm not sure how that interacts with static, though.

羅雙樹 2024-12-16 12:34:58

内联定义不是外部链接的。

// average.h
#ifndef AVERAGE_H
#define AVERAGE_H
inline double average(double a, double b);
#endif

尝试从另一个函数调用具有上述定义的内联函数
模块经过预处理或链接到 ac 文件后将导致错误。

有两种方法可以解决这个问题:

  1. 将其设为静态内联函数定义。
    示例:
// average.h
#ifndef AVERAGE_H
#define AVERAGE_H
static inline double average(double a, double b);
#endif
  1. 包含 c 文件中的定义并将其设为外部
    例子:
#include "average.h"
extern double average(double a ,double b){ 
  return (a + b) / 2;
}

An inline definition is not externally linked.

// average.h
#ifndef AVERAGE_H
#define AVERAGE_H
inline double average(double a, double b);
#endif

Attempting to call an inline function with the definition above from another
module after it has been preprocessed or linked to a c file will result in an error.

There are two ways to solve this problem:

  1. make it a static inline function defintion.
    Example:
// average.h
#ifndef AVERAGE_H
#define AVERAGE_H
static inline double average(double a, double b);
#endif
  1. include the defintion from the c file and make it external.
    Example:
#include "average.h"
extern double average(double a ,double b){ 
  return (a + b) / 2;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文