代码之家  ›  专栏  ›  技术社区  ›  abdo Salm a l i e n w a r e

inline关键字导致Clion中的链接器错误

  •  2
  • abdo Salm a l i e n w a r e  · 技术社区  · 2 年前

    关于 inline 关键字,这只是我写的一个示例代码:

    #include <stdio.h>
    #include <stdint.h>
    
    uint8_t inline LIB_MATH_BTT_u8GetMSBSetBitPos(uint32_t args_u32Variable)
    {
        uint8_t local_u8MSBSetBitPos = 0;
        args_u32Variable = args_u32Variable >> 1;
        while (args_u32Variable != 0)
        {
            args_u32Variable = args_u32Variable >> 1;
            local_u8MSBSetBitPos++;
        }
        return local_u8MSBSetBitPos;
    }
    
    int main() {
        int x  = LIB_MATH_BTT_u8GetMSBSetBitPos(17);
        printf("%d", x);
        return 0;
    }
    

    我在上运行了此代码 Visual studio 2022 结果是:

    4
    

    并且运行了相同的代码 Clion 使用来自的工具链 MinGW 结果是:

    ====================[ Build | untitled | Debug ]================================
    "C:\Program Files\JetBrains\CLion 2022.3.2\bin\cmake\win\x64\bin\cmake.exe" --build C:\Users\User\CLionProjects\untitled\cmake-build-debug --target untitled -j 12
    [1/2] Building C object CMakeFiles/untitled.dir/main.c.obj
    [2/2] Linking C executable untitled.exe
    FAILED: untitled.exe 
    cmd.exe /C "cd . && C:\PROGRA~1\JETBRA~1\CLION2~1.2\bin\mingw\bin\gcc.exe -g  CMakeFiles/untitled.dir/main.c.obj -o untitled.exe -Wl,--out-implib,libuntitled.dll.a -Wl,--major-image-version,0,--minor-image-version,0  -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 && cd ."
    C:\Program Files\JetBrains\CLion 2022.3.2\bin\mingw\bin/ld.exe: CMakeFiles/untitled.dir/main.c.obj: in function `main':
    C:/Users/User/CLionProjects/untitled/main.c:6: undefined reference to `LIB_MATH_BTT_u8GetMSBSetBitPos'
    collect2.exe: error: ld returned 1 exit status
    ninja: build stopped: subcommand failed.
    

    所以我很困惑为什么同样的代码在上成功运行 Visual Studio 2022 但在上失败 Clion

    附言 .代码在上成功工作 Clion 如果我删除 内联 关键字。

    2 回复  |  直到 2 年前
        1
  •  3
  •   Vlad from Moscow    2 年前

    来自C标准(6.7.4函数说明符)

    7任何具有内部链接的函数都可以是内联函数。对于 具有外部链接的功能,则适用以下限制:如果 函数是用内联函数说明符声明的,那么它应该 也可以在相同的翻译单元中定义。如果所有的文件作用域 翻译单元中函数的声明包括内联 没有extern的函数说明符,则中的定义 翻译单元是一个内联定义。 内联定义 没有为函数提供外部定义,也没有 禁止在另一个翻译单元中使用外部定义。内联 定义提供了外部定义的替代方案 翻译器可以使用在 翻译单位。未指定是否调用函数 使用内联定义或外部定义

    所以作为这个函数

    uint8_t inline LIB_MATH_BTT_u8GetMSBSetBitPos(uint32_t args_u32Variable)
    

    具有外部链接,则链接器搜索其外部定义,但未找到它。

    要么需要提供函数的外部定义(使用存储类说明符定义它 extern )或者您可以声明具有内部链接的函数,例如

    static uint8_t inline LIB_MATH_BTT_u8GetMSBSetBitPos(uint32_t args_u32Variable)
    

    在这种情况下,使用具有内部链接的函数的内联定义就足够了。

        2
  •  1
  •   KamilCuk    2 年前

    为什么是相同的代码

    因为不同的编译器会做出不同的决定。通过具有外部链接的内联函数,编译器可以 选择 来自函数的内联版本或外部非内联非静态版本。Clion编译器选择使用外部版本,因为您没有提供外部版本,所以无法编译。

    考虑不使用 inline 。如果你想使用内联,可以考虑研究 为什么? 你想用它吗?它到底是什么意思。如今,编译器足够智能和快速,所以我们可以 static 函数,如果我们希望它们内联的话。