c - 头文件与源文件中的内联函数定义

标签 c gcc inline

我对如何在 c(C99 及更高版本)中内联函数感到困惑。在“C 编程,一种现代方法”(K.N. King,第 2 版)的第 18.6 节中,或者例如 this 中的 3教程(在“使用内联函数的策略”下),内联函数的定义在头 (.h) 文件中给出,然后该函数在源 (.c) 文件中再次列为 extern。

例如,我在做什么:在 header “stencil.h”中

#ifindef _STENCIL_H
#define _STENCIL_H

inline double D1_center_2ndOrder(double vp1, double vm1, double dr) 
{
    return (vp1-vm1) / (2.0 * dr) ;
}

#endif 

然后在匹配的源文件“stencil.c”中定义

#include "stencil.h"

extern double D1_center_2ndOrder(double vp1, double vm1, double dr) ;

我这样做了,然后在文件“main.c”中我调用了 average:

#include <stdio.h>
#include <stdlib.h>

#include "stencil.h"

int main(int argc, char *argv[])
{
    double vp1 = 1 ; 
    double vp2 = 2 ;
    dr = 0.1 ;

    double der_v = D1_center_2ndOrder(vp1, vm1, dr) ; 
    printf("der_v\t%f\n", der_v) ;

    return 0 ; 
}

我用下面的makefile编译一切

CC = gcc 

CFLAGS = -Wall -lm -std=gnu11  

OBJECTS = main.o stencil.o

DEPS_MAIN = stencil.h

test: $(OBJECTS)
    $(CC) -o collapse $(OBJECTS) $(CFLAGS)

main.o: main.c $(DEPS_MAIN)
    $(CC) -c main.c

stencil.o: stencil.c stencil.h
    $(CC) -c stencil.c

然后我得到以下编译器错误:

gcc  -c main.c
gcc  -c stencil.c
gcc  -o test main.o stencil.o -Wall -lm -std=gnu11 
stencil.o: In function `D1_center_2ndOrder':
stencil.c:(.text+0x0): multiple definition of `D1_center_2ndOrder'
main.o:main.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
make: *** [collapse] Error 1

当我在 .c 源文件“stencil.c”中定义函数并在头文件中声明它时,我没有收到上述错误。我使用的 gcc 版本是 gcc (GCC) 4.8.5 20150623(红帽 4.8.5-28)。

我的问题是:

(1) 为什么“C 编程,一种现代方法”和我在网上找到的关于内联函数的教程建议在头文件中定义函数并在源文件中再次将其列为 extern?这样做会给我一个编译器错误。

(2) 当我在头文件中声明内联函数然后在源文件中定义为 extern 时,编译器是否仍会内联我的函数?

最佳答案

您使用的是基于标准 C99(及更新版本)的可移植策略,这是完全正确的。

失败是因为您使用默认的 -std 设置调用 gcc,对于 GCC 4.8.5,这有效地告诉它使用其遗留语义而不是标准 C11 语义。 -std 的默认值在 4.8.5 版中是 gnu90。在版本 5 中,它被更改为 gnu11,它实现了 C99/C11 inline 语义。

您正在使用默认设置,因为您的 Makefile 没有在编译配方中包含 $(CFLAGS);仅在最终链接配方中。 (您可以在 make 打印出的命令中看到这一点)。

虽然 -std=gnu11 应该可以工作,但最好改用 -std=c11。并考虑升级到更新的 GCC 版本。

关于c - 头文件与源文件中的内联函数定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53051814/

相关文章:

C - 打乱结构体数组

c - C中的链表合并排序实现中丢失的节点

c - 如何获取电子邮件地址的开头

c - 如何使用Arduino在LCD上闪烁单个字符而没有延迟()方法?

html - 如何强制 <noscript> 内联并继承 CSS 样式?

c++ - 使用临时函数对象进行全局初始化

c - 静态链接 ncurses 到程序

linux - 为什么在 Linux/ARMv7 上编译我的代码时 sinf() 这么慢?

jQuery UI slider : how to inline it?

css - 如何使用 <span> 缩进后续文本行