Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 头文件与源文件中的内联函数定义_C_Gcc_Inline - Fatal编程技术网

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

C 头文件与源文件中的内联函数定义,c,gcc,inline,C,Gcc,Inline,我对如何在c(C99以后)中内联函数感到困惑。在“C编程,现代方法”(K.N.King,第二版)的第18.6节中,或例如教程中的第3节(在“使用内联函数的策略”下),内联函数的定义在头(.h)文件中给出,然后该函数在源(.C)文件中再次作为外部函数列出 例如,我正在做什么:在标题“stencil.h”中 然后在匹配的源文件“stencil.c”中定义 #include "stencil.h" extern double D1_center_2ndOrder(double vp1, double

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

例如,我正在做什么:在标题“stencil.h”中

然后在匹配的源文件“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 ; 
}
然后我得到以下编译器错误:

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,对于GCC4.8.5,该设置有效地告诉它使用其遗留语义,而不是标准的C11语义。版本4.8.5中的默认值为gnu90。在版本5中,它被更改为
gnu11
,它实现了C99/C11
inline
语义

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


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

< p>编译时需要传递标准版本标志。当你在链接阶段通过它时,它没有任何好处

因此,您的makefile应该类似于:

CC = gcc 

CFLAGS = -Wall -std=gnu11
LDFLAGS = -lm

OBJECTS = main.o stencil.o

DEPS_MAIN = stencil.h


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

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

stencil.o: stencil.c stencil.h
    $(CC) -c stencil.c $(CFLAGS)
我已经用这个shell脚本测试了您的示例:

#!/bin/sh -eu
cat > stencil.h <<EOF
#ifndef _STENCIL_H
#define _STENCIL_H

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

#endif
EOF
cat > stencil.c <<EOF
#include "stencil.h"
extern double D1_center_2ndOrder(double vp1, double vm1, double dr) ;
EOF
cat > main.c <<EOF
#include <stdio.h>
#include <stdlib.h>

#include "stencil.h"

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

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

    return 0 ;
}
EOF
: ${CC:=gcc}
set -x
gcc -c main.c -std=c99
gcc -c stencil.c -std=c99
gcc -o test main.o stencil.o -lm 
#/bin/sh-欧盟

cat>stencil.h您对
-std=c99
c11
有相同的结果吗?@Mat是的,-std=c99和-std=c11仍然存在错误。另请参见和(在较小程度上是)。@mooingduck:看看标准中的这个示例:。像那样使用
extern
是符合标准的。为什么使用-std=c11比使用-std=gnu11“更好”?@justin:因为它会让你知道你是否使用了gcc扩展,这可能会导致其他编译器出现问题。
CC = gcc 

CFLAGS = -Wall -std=gnu11
LDFLAGS = -lm

OBJECTS = main.o stencil.o

DEPS_MAIN = stencil.h


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

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

stencil.o: stencil.c stencil.h
    $(CC) -c stencil.c $(CFLAGS)
#!/bin/sh -eu
cat > stencil.h <<EOF
#ifndef _STENCIL_H
#define _STENCIL_H

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

#endif
EOF
cat > stencil.c <<EOF
#include "stencil.h"
extern double D1_center_2ndOrder(double vp1, double vm1, double dr) ;
EOF
cat > main.c <<EOF
#include <stdio.h>
#include <stdlib.h>

#include "stencil.h"

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

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

    return 0 ;
}
EOF
: ${CC:=gcc}
set -x
gcc -c main.c -std=c99
gcc -c stencil.c -std=c99
gcc -o test main.o stencil.o -lm