我有一个关于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.如果我删除关键字inline,代码将在Clion上成功运行.

推荐答案

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

7任何具有内部链接的函数都可以是内联函数.为. 函数,则适用以下限制:如果 函数是用内联函数说明符声明的,则它应该 也在同一翻译单元中定义.如果所有文件作用域 翻译单元中函数的声明包括内联 不带外部的函数说明符,然后其中的定义 翻译单位是内联定义.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.

所以当这个函数

uint8_t inline LIB_MATH_BTT_u8GetMSBSetBitPos(uint32_t args_u32Variable)

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

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

static uint8_t inline LIB_MATH_BTT_u8GetMSBSetBitPos(uint32_t args_u32Variable)

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

C++相关问答推荐

如何在不修改字符串缓冲区早期使用的情况下覆盖字符串缓冲区

如何通过Zephyr(Devicetree)在PR Pico上设置UTE 1?

了解一些CLIPS原语数据类型

错误:C中需要参数声明符

ATmega328P USART发送字符重复打印

警告:C++中数组下标的类型为‘char’[-Wchar-subpts]

为什么内核使用扩展到前后相同的宏定义?

如果包含路径不存在,我的编译器可以被配置为出错吗?(GCC、MSVC)

为什么I2C会发送错误的数据?

调用mProtection将堆栈上的内存设置为只读,直接导致程序SIGSEGV

使用TCL C API导航到列表中的元素

将字符串数组传递给C中的函数:`str[dim1][str_size]`vs`*str[dim1]`

静态初始化顺序失败是否适用于C语言?

如何在C中定义指向函数的指针并将该指针赋给函数?

将复合文字数组用作临时字符串缓冲区是否合理?

令人困惑的返回和 scanf 问题相关

在列表中查找素数

C/C++编译器可以在编译过程中通过按引用传递来优化按值传递吗?

多行表达式:C 编译器如何处理换行符?

如何让 unlinkat(dir_fd, ".", AT_REMOVEDIR) 工作?