typedef in C
笔者对C语言只是知道简单的使用方法,并不是非常精通。近日在Redis的 server.h 文件中发现了这样的代码:
1 | typedef void redisCommandProc(client *c); |
对于此处的 typedef 语句感到较为迷惑。就以前所知,C语言中的 typedef 就是用于创建一个数据类型的别名的关键字。此处的 typedef 语句应该是一个函数指针类型的别名. 而在结构体redisCommand中的 proc成员应该就是一个指向函数的指针,该函数接受一个client指针作为参数,返回为空。
函数指针类型的别名在笔者印象中应该采用如下的方式声明:
1 | typdef type (*funcptr)(args...); |
此处,假设需要声明一个函数指针,其参数为一个client指针,返回为空,那么应该如此声明:
1 | typedef void (*redisCommandProc)(client *c); |
在Redis源码中的这个声明并没有显示将redisCommandProc声明成一个指针。那么这两种声明方式又有什么异同呢?于是笔者写了一个简单的测试:
1 |
|
此处采用的编译器信息为:
1 | Apple LLVM version 9.0.0 (clang-900.0.39.2) |
获得了如下的输出:
1 | funca_with_reference 0x104f34e40, funca_without_reference 0x104f34e40 |
根据上述结果可以看出,本质上,Redis中的声明方式:
1 | typedef void redisCommandProc(client *c); |
本质上是对函数类型的一个别名,而非对函数指针的一个别名。当使用的时候,需要使用 redisCommandProc * 来声明一个指向函数的指针 ,如果遗漏了指针声明,则会变成一个函数类型,将会产生编译时的错误。
对于C语言中的函数名与函数指针,本质上二者并没有差别,都是存储了指向该函数的地址。因此,以下的调用其实是一样的:
1 | func('a'); |
以上可以从 C99 Specification 中的 6.3.2.1.4 获得认证:
a function designator with type “function returning type” is converted to an expression that has type “pointer to function returning type”