一个简单的inline函数
inline void swap(char *x, char *y){char t = *x; *x=*y; *y=t;}
编译的时候报错
gcc --std=c11 -Wall -c -o permutation.o permutation.c
gcc permutation.o -lgmp -o permutation
permutation.o:permutation.c:(.text+0x92):对‘swap’未定义的引用
permutation.o:permutation.c:(.text+0x92): 截断重寻址至相符: R_X86_64_PC32 针对未定义的符号 swap
permutation.o:permutation.c:(.text+0xcb):对‘swap’未定义的引用
permutation.o:permutation.c:(.text+0xcb): 截断重寻址至相符: R_X86_64_PC32 针对未定义的符号 swap
collect2: 错误:ld 返回 1
make: *** [<内置>:permutation] 错误 1
# 编译器版本
$ gcc --version
gcc (GCC) 9.1.0
Copyright © 2019 Free Software Foundation, Inc.
本程序是自由软件;请参看源代码的版权声明。本软件没有任何担保;
包括没有适销性和某一专用目的下的适用性担保。
解决办法
方法1. 开启 -O 优化
gcc -O -c -o permutation.o permutation.c
gcc permutation.o -lgmp -o permutation
方法2. 添加非inline的原型声明
void swap(char *x, char *y);
inline void swap(char *x, char *y){char t = *x; *x=*y; *y=t;}
cc --std=c11 -Wall -c -o permutation.o permutation.c
gcc permutation.o -lgmp -o permutation
方法3. 声明时同时使用static关键字
static inline void swap(char *x, char *y){char t = *x; *x=*y; *y=t;}
$ make permutation
gcc --std=c11 -Wall -c -o permutation.o permutation.c
gcc permutation.o -lgmp -o permutation
原因
生成汇编代码,查看swap函数的情况,做成表格如下
总结
一开始出现编译错误的原因是对swap的调用是真的调用(没有转换成内嵌代码),同时还没有输出swap的对应的汇编代码。
C中定义内联函数要同时使用static inline
修饰符,这样生成的代码开启优化选项后不输出汇编代码,直接内嵌调用(一般情况);如果添加非inline函数原型,相当于extern inline swap(){...}
,即使开启优化选项,也会生成相应的汇编代码,只不过本地调用直接内嵌(一般情况)。
C和C++不一样,C++的inline函数自带static属性,而C中的需要显式指定static才行。
完整代码
#include <stdio.h>
#include <string.h>
#define MX 20
// 输出给定子串的全排
void perm_recursive(char *s, int n);
char buf[MX] = "ABCD";
int main(void){
perm_recursive(buf, strlen(buf));
return 0;
}
inline void swap(char *x, char *y){char t = *x; *x=*y; *y=t;}
// 全排的递归实现
static void __perm(char *s, int n, int off){
if (off == n-1){
printf("%s", s);
printf("\n");
}else{
for (int k = off; k<n; k++){
swap(s+off, s+k);
__perm(s, n, off+1);
swap(s+off, s+k);
}
}
}
void perm_recursive(char *s, int n){
if (n<1) return;
__perm(s, n, 0);
}
参考链接
gcc 9.2 文档中inline函数 6.45 An Inline Function is As Fast As a Macro