1.泛型函数
C11新增了关键字 _Generic,可用于处理泛型函数
用法
_Generic(x, int: "int", double: "double", default: "other");
编译器会根据传入的x来推断类型,然后与后面的标签匹配。
可结合宏定义来达到一定的泛型的目的
演示
#define get_type(x) _Generic(x, int: "int", double: "double", char: "char", default: "other")
假设有一个交换函数,我们可以在一个头文件中声明其不同的版本,然后再宏定义一个swap函数,标签对应的是函数指针。在其他文件中调用交换函数只需要调用宏定义版本的函数即可。
2.内联函数
宏函数有些像内联函数,抛开宏函数的特性,实际上二者也没有多少差别,定义方法和C++一样,声明,然后inline修饰定义函数,如果想让其具有内部链接性可用static修饰。
如果用static修饰函数,可以不用声明函数
演示
inline static void swap(int * a, int * b)
{
int temp = *a;
*a = *b;
*b = temp;
}
由于static的修饰,使得内联函数具有内部链接性,可考虑把内联函数封装在一个有文件中。
与C++不同的是,C允许内联函数和外部链接的函数混合使用。但是会优先调用用stati修饰的内部连接性的内联函数。只有inline修饰的函数则表明可被替换为外部定义的函数,但是能声明,否则会发生函数重复定义。
func.c
#include <stdio.h>
void func()
{
printf("外部链接函数调用\n");
}
main.c
#include <stdio.h>
inline void func()
{
printf("use func function\n");
}
int main()
{
func();
return 0;
}
运行结果
3.不返回主函数的函数
C11新增的函数说明符 _Noreturn
用法
_Noreturn void swap(int * a, int * b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int x,y;
x = 10;
y = 20;
swap(&x, &y);
printf("x is %d\ny is %d\n",x,y);
return 0;
}
printf函数并不会被执行,而是直接退出程序。
exit函数就是这个函数的一个示例。
值得一提的是,虽然用_Noreturn修饰的函数不会返回主函数,但是其也有返回值声明,和普通函数一样,在默认的情况下是int,但是对于_Noreturn函数而言,编写程序的人有责任应该指定的声明其函数返回值为void,以免造成误解。
4.可变参数函数
要使用可变参数函数这一技术,要包含头文件stdargs.h
下面是一个方便说明的例子
#include <stdio.h>
#include <math.h>
#include <stdarg.h>
inline static double sum(int args, ...)
{
double ans = 0;
va_list ap;
va_list ap_copy;
va_copy(ap_copy, ap);
va_start(ap, args); //initialized ap to argument list
//访问列表中的内容
ans += va_arg(ap,int);
ans += va_arg(ap,double);
va_end(ap);
return ans;
}
int main()
{
double ans = sum(2,3,3.14);
printf("%.2lf", ans);
return 0;
}
1.首先,提供一个这样的函数原型
返回值类型 函数名(参数个数, ...)
...代表的是参数列表,也就是具体的参数
2.然后需要一个专门储存参数列表的类型,即va_list.
3.对其进行初始化使,即va_start函数,接受一个va_list变量和一个整形变量。作用是将va_list变量初始化为参数列表中的内容,即...中的内容
可以使用va_copy对va_list变量进行复制
4.使用va_arg宏函数具体的使用参数
第n次调用va_args会返回参数列表中的第n项。并且,这种操作是不可回溯的,所以,有时候可能用va_copy来进行va_list的对象拷贝。
5.进行清理操作
由于va_list内部存储是由malloc开辟的堆区空间,所以要进行内存的清理工作。
va_end对va_list变量进行内存的free操作,释放其所占的内存。
简单的demo
#include <stdio.h>
#include <stdarg.h>
double sum(int, ...);
int main()
{
double s, t;
s = sum(3, 1.1, 2.5, 13.3);
t = sum(6, 1.1, 2.1, 13.1, 4.1, 5.1, 6.1);
printf("s is %.2lf\nt is %.2lf\n",s,t);
return 0;
}
double sum(int args, ...)
{
va_list ap;
double tot = 0;
va_start(ap,args);
for(int i=0;i<args;++i)
{
tot += va_arg(ap,double);
}
va_end(ap);
return tot;
}