再谈 typedef(重点为函数指针)

有种很方便的写法。

typedef int *p;
p pointer;

这时直接把pointer带入原式中,取代p然后去掉typedef,得到的结果就是int * pointer;
哈哈,这样直接替换就很直观多了。
C 语言语法简单,但内涵却博大精深;如果在学习时只是止步于表面,那么往往后期
会遇到很多困难。typedef 是 C 语言中一个很好用的工具,大量存在于已有代码中,特别值
得一提的是:C++标准库实现中更是对 typedef 有着大量的使用。但很多初学者对其的理解
仅局限于:typedef 用来定义一个已有类型的”别名(alias)”。正是因为有了这样的理解,才有
了后来初学者在 typedef int myint 和 typedef myint int 之间的犹豫不决。很多国内大学的 C
语言课之授课老师也都是如是说的,或者老师讲的不够透彻,导致学生们都是如是理解的。
我这里想结合 C 语言标准文档以及一些代码实例,也说说

typedef。
int *p;

这样的代码是 C 语言中最最基础的一个语句了,大家都知道这个语句声明了一个变量
p,其类型是指向整型的指针(pointer to int);如果在这个声明的前面加上一个 typedef 后,
整个语义(semantics)又会是如何改变的呢?
typedef int *p;
我们先来看看 C99 标准中关于 typedef 是如何诠释的?C99 标准中这样一小段精辟的
描述:

“In a declaration whose storage-class specifier is typedef, each
declarator defines an identifier to be a typedef name that denotes the
type specified for the identifier in the way described in xx”.

参照这段描述,并拿 typedef int *p 作为例子来理解:在一个声明中,如果有存储
类说明符 typedef 的修饰,标识符 p 将被定义为了一个 typedef name,这个 typedef name
表示(denotes)一个类型,什么类型呢?就是 int p 这个声明(declarator)中标识符
(indentifier)p 的类型(int
)。
再比对一下两个声明:

int *p;
typedef int *p;

是不是有点”茅舍顿开”的感觉,int *p 中, p 是一个变量,其类型为 pointer to int;在 int
*p 前面增加一个 typedef 后,p 变为一个 typedef-name,这个 typedef-name 所表示的类型
就是 int p 声明式中 p 的类型(int)。说句白话,typedef 让 p 去除了普通变量的身份,摇身
一变,变成了 p 的类型的一个 typedef-name 了。
为了巩固上面的理解,我们再来看看”C 语言参考手册(C: A Reference Manual)”中的说
法:任何 declarator(如 typedef int *p)中的 indentifier(如 p)定义为 typedef-name, 其(指
代 p)表示的类型是 declarator 为正常变量声明(指代 int p)的那个标识符(指代 p)的类型
(int
)。有些绕嘴,不过有例子支撑:
[例 1]

typedef double MYDOUBLE;

分析:
去掉 typedef ,得到正常变量声明=> double MYDOUBLE;
变量 MYDOUBLE 的类型为 double;
=> “typedef double MYDOUBLE”中 MYDOUBLE 是类型double 的一个 typedef-name。
MYDOUBLE d; <=> d 是一个 double 类型的变量
[例 2]

typedef double *Dp;

分析:
去掉 typedef ,得到正常变量声明=> double Dp;
变量 Dp 的类型为 double
,即 pointer to double;
=> “typedef double Dp”中 Dp 是类型 double的一个 typedef-name。
Dp dptr; <=> dptr 是一个 pointer to double 的变量
[例 3]

typedef int* Func(int);

分析:
去掉 typedef ,得到正常变量声明=> int* Func(int);
变量 Func 的类型为一个函数标识符,该函数返回值类型为 int*,参数类型为 int;
=> “typedef int* Func(int)”中 Func 是函数类型(函数返回值类型为 int*,参数类型为 int)
的一个 typedef-name。
Func *fptr; <=> fptr 是一个 pointer to function with one int parameter, returning a
pointer to int
Func f; 这样的声明意义就不大了。
[例 4]

typedef int (*PFunc)(int);

分析:
去掉 typedef ,得到正常变量声明=> int (*PFunc)(int);
变量 PFunc 的类型为一个函数指针,指向的返回值类型为 int,参数类型为 int 的函数
原型;
=> “typedef int (*PFunc)(int)”中 PFunc是函数指针类型(该指针类型指向返回值类型为
int,参数类型为 int 的函数)的一个 typedef-name。
PFunc fptr; <=> fptr 是一个 pointer to function with one int parameter, returning int

#include "iostream"
using namespace std;
int add(int a,int b){
return (a+b);
}
typedef int (* func)(int ,int ) ;
void main(){
func f = add;
int n = f(1,2);
cout << n << endl;
}

[例 5]

typedef int A[5];

分析:
去掉 typedef ,得到正常变量声明 => int A[5];
变量 A 的类型为一个含有 5 个元素的整型数组;
=> “typedef int A[5]”中 A 是含有 5 个元素的数组类型的一个 typedef-name。
A a = {3, 4, 5, 7, 8};
A b = { 3, 4, 5, 7, 8, 9}; /* 会给出 Warning: excess elements in array initializer */
[例 6]

typedef int (*A)[5]; //(注意与 typedef int* A[5]; 区分)

分析:
去掉 typedef ,得到正常变量声明 => int (*A)[5];
变量 A 的类型为 pointer to an array with 5 int elements;
=> “typedef int (*A)[5]“中 A 是”pointer to an array with 5 int elements”的一个
typedef-name。
int c[5] = {3, 4, 5, 7, 8};
A a = &c;
printf(”%d\n”, (a)[0]); / output: 3 /
如果这样赋值:
int c[6] = {3, 4, 5, 7, 8, 9};
A a = &c; /
 会有 Warning: initialization from incompatible pointer type */
[例 7]

typedef struct _Foo_t Foo_t;

分析:
去掉 typedef ,得到正常变量声明 => struct _Foo_t Foo_t;
变量 Foo_t 的类型为 struct _Foo_t;
=> “typedef struct _Foo_t Foo_t”中 Foo_t 是”struct _Foo_t”的一个 typedef-name。
[例 8]
typedef struct { … // } Foo_t;
分析:
去掉 typedef ,得到正常变量声明 => struct { … // } Foo_t;
变量 Foo_t 的类型为 struct { … // } ;
=> “typedef struct { … // } Foo_t “中 Foo_t 是”struct { … // }”的一个 typedef-name。
这里 struct {…//}是一个无”标志名称(tag name)”的结构体声明。

转载:https://wenku.baidu.com/view/2a1689cada38376baf1fae79.html

原文地址:http://www.cnblogs.com/amxiang/p/16897654.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性