提问人:abdo Salm 提问时间:8/6/2023 最后编辑:Vlad from Moscowabdo Salm 更新时间:8/6/2023 访问量:54
inline 关键字导致 Clion 中的链接器错误
inline keyword causes linker error in Clion
问:
我有一个关于关键字的奇怪错误,这只是我写的示例代码: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 上失败。
PS的。如果我删除了关键字,代码在 Clion 上成功运行。inline
答:
为什么使用相同的代码
因为不同的编译器会做出不同的决定。具有具有外部链接的内联函数允许编译器从函数的内联版本或外部非内联非静态版本中进行选择。Clion 编译器选择使用外部版本,因为您没有提供外部版本,因此无法编译。
考虑不使用 .如果你想使用内联,请考虑研究你为什么要使用它,以及它的确切含义。如今,编译器足够智能且足够快,因此如果我们希望它们内联,我们可以只使用函数。inline
static
来自 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)
在这种情况下,使用具有内部链接的函数的内联定义就足够了。
评论
cels
具有外部链接并被引用,所以外部定义必须出现在另一个翻译单元中”
评论