再谈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)"的结构体声明。
参考资料:
1、"ISOIEC-98991999(E)--Programming Languages--C"之Page 123;
2、C语言参考手册(中文版) 之 Page 119
再谈typedef(重点为函数指针)相关推荐
- typedef定义的函数指针
再谈 typedef(重点为函数指针) 有种很方便的写法. typedef int *p: p pointer: 这时直接把pointer带入原式中,取代p然后去掉typedef,得到的结果就是int ...
- 【C/C 】浅谈C/C 中函数指针与回调函数
01.函数指针 1.1.函数指针定义 一个函数总是占用一段连续的内存区域,函数名在表达式中有时也会被转换为该函数所在内存区域的首地址,这和数组名非常类似.我们可以把函数的这个首地址(或称入口地址)赋予 ...
- 再谈正态分布或高斯函数
它的历史不知道,如何推导出来的,没管啊,不过我很有兴趣看看啊,但没有看.高斯函数的用处太多了: 首先说明一点哦:正态分布是高斯函数的积分为1的情况: 一维情况下: 一维高斯高斯函数的公式: 而正态分布 ...
- typedef 返回类型(*Function)(参数表) ——typedef函数指针
//首先看一下函数指针怎么用 #include <iostream> using namespace std; //定义一个函数指针pFUN,它指向一个返回类型为char,有一个整型的参数 ...
- 结合typedef更为直观的应用函数指针
"函数指针"的本质是一个指针变量,只不过该指针变量指向函数. 1:简单应用 形式1:返回类型(*函数名)(参数表) [html] view plaincopy #include & ...
- typedef和函数指针定义
2019独角兽企业重金招聘Python工程师标准>>> 用typedef为一个函数指针类型起别名 typedef int (*p1)(int,int); 定义一个函数指针 int ( ...
- typedef函数指针
由于之前学习C++这块内容并没有经过太多实践,这块内容已经忘记了不少,现在学到动态库用到这块内容,又重新整理了.接下来的几天将会学习更多的动态库静态库的知识,学完之快内容之后,就学习excel等off ...
- 函数指针,指针函数,函数指针数组
这是一个群友发的笔试题目,里面涉及的东西也比较有意思. 直接看代码 void (*f[])(char *) 这个是个什么东西? 我们先看看下面的东西 函数指针和指针函数的定义 我们看个代码 int * ...
- C 基础——指针函数与函数指针
一.指针函数的定义 指针函数,顾名思义,返回指针的函数.其一般定义形式如下: 类型名 *函数名(函数参数列表): 其中,后缀运算符括号()表示这是一个函数,其前缀运算符星号*表示此函数为指针型函数,其 ...
最新文章
- ad 原理图差分线_usb hub原理图及pcb设计
- STL中各容器和适配器类的定义
- scrapy-splash抓取动态数据例子三
- PyQt5 笔记5 -- 消息框(QMessageBox)
- python可以这样学读书笔记_Python小白的读书笔记
- Android 8.0学习(25)---系统的应用图标适配
- 量子计算机西南交大,交大量子光电实验室
- 合成谬误与公地悲剧(为何设置产品总监职位及核算名义成本)
- [undo]ip address ppp-negotiate
- cs229线性回归和逻辑回归总结
- 安信可推荐 | 安信可ESP-C3模组和ESP32-S3模组的软件和硬件对比区别
- RuntimeError: Exporting the operator affine_grid_generator to ONNX opset version 9 is not supported.
- QT 使用 qcustomplot 编译出错
- 百宝云COM组件操作教程
- android 9.0 10.0 上报鼠标左键右键给app调用
- POS标记——HMM模型
- Python Web简介
- 中国保险中介行业市场规模调研及投资可行性研究报告2022-2027年
- html手指动图,推荐10款gif动态图片特效(收藏)
- 2022年520最实用的礼物,苹果平板的触控笔
热门文章
- 投影html连接电脑,电脑怎么连接投影仪?投影仪的详细安装使用教程
- 计算机桌面图标有箭头,电脑桌面图标为什么会有一个小箭头,原来没的呀,
- [人工智能]手语识别转文字落地深圳医院,厉害了我的腾讯
- MongoDB 3.0+访问数据库的方法
- 计算机辅助外文文献,计算机辅助设计建筑CAD论文中英文对照资料外文翻译文献.doc...
- 手机辐射到底有多厉害!65分钟将生鸡蛋煮熟
- 科学解释成功者成功的秘诀
- 格力电器成为银隆新能源股东 持股30.47%
- 京东集团副总裁王楠:数智化是打造国际消费中心城市的必由之路
- 赔了24亿,干到中国第一!最“不要命”航班,竟让无数人抢着坐?