内联函数 square 为什么无法工作?

huangapple go评论79阅读模式
英文:

Why can not the inline function square work?

问题

我有2个C源文件:

file1.c:

#include <stdio.h>

void masp(double);

int main()
{
    masp(1.6);
    return 0;
}

file2.c:

#include <stdio.h>

inline double square(double x) 
{ 
    return (int) (x * x + 0.5); 
}

void masp(double w)
{
    double kw = square(w);
    printf("%.2f\n", kw);
    return;
}

编译命令是:
gcc file1.c file2.c -o files

为什么会出现错误:

Undefined symbols for architecture x86_64:
"_square", referenced from:
_masp in ccMowbTf.o

英文:

I have 2 C source files:


file1.c:

#include &lt;stdio.h&gt;

void masp(double);

int main()
{
    masp(1.6);
    return 0;
}

file2.c:

#include &lt;stdio.h&gt;

inline double square(double x) 
{ 
    return (int) (x * x + 0.5); 
}

void masp(double w)
{
    double kw = square(w);
    printf(&quot;%.2f\n&quot;, kw);
    return;
}

the compile command is:
gcc file1.c file2.c -o files


why do I get an error:

Undefined symbols for architecture x86_64:
"_square", referenced from:
_masp in ccMowbTf.o

答案1

得分: 1

OP的函数声明为inline double square(double);(实际上在OP的代码中作为函数定义的一部分声明),并且在同一翻译单元中有一个定义。由于该函数没有内部链接(即未声明为static,也未明确声明为extern),内联函数定义不构成该函数的外部定义。对于未声明内部链接的函数调用(即未声明为static的函数),编译器可以选择使用函数的内联定义或调用外部函数。在OP的情况下,编译器选择调用外部函数,但没有提供具有外部链接的函数定义,因此程序链接失败。

有三种可能的解决方案:

  1. 要么:将函数声明为static inline,以使函数定义成为具有内部链接的内联函数。编译器可以自由地将对函数的调用翻译为实际函数调用或内联函数调用,其中inline关键字充当提示编译器的标志,表明程序员更喜欢内联调用。
  2. 要么:提供函数的外部定义。可以通过在不带inline说明符的情况下复制函数定义,或者通过显式添加extern说明符到现有的内联定义(将其声明为extern inline)来完成。
  3. 要么:移除inline说明符,将函数定义转为外部函数定义。

参考C17/C18标准第6.7.4节的第6和第7段以及脚注140、141和142,可以得到更多信息。

英文:

OP's function is declared as inline double square(double); (actually declared as part of the function definition in OP's code) and has a definition in the same translation unit. Because the function does not have internal linkage (i.e. it was not declared static, and was not explicitly declared extern, the inline function definition does not constitute an external definition of the function. For a call to a function not declared with internal linkage (i.e. not declared static), the compiler is free to use an inline definition of the function or to call the external function. In OP's case, the compiler chose to call the external function, but no definition of the function with external linkage has been provided, so the program failed to link.

There are three possible solutions:

  1. Either: declare the function as static inline so that the function definition is an inline function with internal linkage. The compiler is free to translate calls to the function as an actual function call or as an inline function call, with the inline keyword acting as a hint to the compiler that inline calls are preferred by the programmer.
  2. Or: provide an external definition of the function. That can be done either by duplicating the function definition without the inline specifier, or by explicitly adding the extern specifier to the existing inline definition (declaring it as extern inline).
  3. Or: remove the inline specifier to turn the function definition into an external function definition.

For reference, see C17/C18 section 6.7.4 paragraphs 6 and 7 and footnotes 140, 141 and 142:

> 6. A function declared with an inline function specifier is an inline function. Making a function an inline function suggests that calls to the function be as fast as possible.<sup>140)</sup> The extent to which such
suggestions are effective is implementation-defined.<sup>141)</sup>
> 7. Any function with internal linkage can be an inline function. For a function with external linkage, the following restrictions apply: If a function is declared with an inline function specifier, then it shall also be defined in the same translation unit. If all of the file scope declarations for a function in a translation unit include the inline function specifier without extern, then the definition in that translation unit is an inline definition. An inline definition does not provide an external definition for the function, and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition.<sup>142)</sup>
> ---
> <sup>140)</sup> By using, for example, an alternative to the usual function call mechanism, such as “inline substitution”. Inline substitution is not textual substitution, nor does it create a new function. Therefore, for example, the expansion of a macro used within the body of the function uses the definition it had at the point the function body appears, and not where the
function is called; and identifiers refer to the declarations in scope where the body occurs. Likewise, the function has a single address, regardless of the number of inline definitions that occur in addition to the external definition.<br />
<sup>141)</sup> For example, an implementation might never perform inline substitution, or might only perform inline substitutions to
calls in the scope of an inline declaration.<br />
<sup>142)</sup> Since an inline definition is distinct from the corresponding external definition and from any other corresponding inline definitions in other translation units, all corresponding objects with static storage duration are also distinct in each of the definitions.

答案2

得分: 0

使用GCC编译内联函数时,需要启用优化:

内联函数 square 为什么无法工作?

或者将其定义为extern(以添加外部链接):

extern inline double square(double x) 
{ 
    return (x * x + 0.5); 
}

或者将其定义为static

static inline double square(double x) 
{ 
    return (x * x + 0.5); 
}

https://godbolt.org/z/qx1q6xM1K

内联函数 square 为什么无法工作?

顺便说一句,不需要两个文件来重现这个行为:
https://godbolt.org/z/3heanfWT3

内联函数 square 为什么无法工作?

英文:

Using GCC to compile inline function you need to enable optimizations:

https://godbolt.org/z/bG6s458ef

内联函数 square 为什么无法工作?

or to define it as extern (to add an external linkage):

extern inline double square(double x) 
{ 
    return (x * x + 0.5); 
}

or make it static

static inline double square(double x) 
{ 
    return (x * x + 0.5); 
}

https://godbolt.org/z/qx1q6xM1K

内联函数 square 为什么无法工作?

BTW it is not necessary to have two files to reproduce this behaviour:
https://godbolt.org/z/3heanfWT3

内联函数 square 为什么无法工作?

答案3

得分: -1

By stating that the function is inline, you are hinting the compiler that you want it "copy and paste" the function into other functions.

This leads the compiler to not actually define a new function for the square function, but instead it just pastes its implementation in the masp function.

To fix this issue, you can either:

  1. Remove the inline directive.
  2. Move the inline function to a header file and include it from both files.
英文:

By stating that the function is inline, you are hinting the compiler that you want it "copy and paste" the function into other functions.
内联函数 square 为什么无法工作?

This leads the compiler to not actually define a new function for the square function, but instead it just pastes it's implementation in the masp function.

To fix this issue, you can either:

  1. Remove the inline directive.
  2. Move the inline function to a header file and include it from both files.

huangapple
  • 本文由 发表于 2023年3月15日 17:38:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75742878.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定