热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

c语言typedef函数,C语言的typedef

typedef是一种有趣的声明形式:它为一种类型引入新的名字,而不是为变量分配空间。在某些方面,typedef类似于宏文本替换——它并没有

typedef是一种有趣的声明形式:它为一种类型引入新的名字,而不是为变量分配空间。在某些方面,typedef类似于宏文本替换——它并没有引入新的类型,而是为现有类型取个新名字,但它们之间存在一个关键性的区别。

typedef关键字可以是一个常规声明的一部分,可以出现在靠近声明开始部分的任何地方。事实上,typedef 的格式与变量声明完全一样,只是多了这个关键字,向你提醒它的实质。由于typedef看上去跟变量声明完全一样,它们读起来也是一样的。普通的声明表示“这个名字是一个指定类型的变量”,而typedef关键字并不是创建一个变量,而是宣称“这个名字是指定类型的同义词”。

一般情况下,typedef用于简洁的表示指向其他东西的指针。典型的例子是signal()原型的声明。signal()是一种系统调用,用于通知运行时系统:当某种特定的“软件中断”发生时调用特定的程序。调用signal()并通过传参告诉它中断的类型以及用于处理中断的程序。在ANSI C标准中,signal()的声明如下:

void (*signal(int sig,void(*func)(int)))(int);

用分析C语言的声明(2)介绍的方法分析这个声明:

首先:

void (*signal( ))(int);

signal是一个函数,它返回一个函数指针,后者所指向的函数接受一个int参数并返回void。

其中提取出来的通用的部分是:

void (*func)(int);

这个表示一个函数指针,所指向的函数接受一个int参数,返回值是void。下面用typedef来“代表”通用部分,从而进行简化:

typedef void (*ptr_to_func) (int);

/* 它表示ptr_to_func是一个函数指针,该函数接受一个int参数,返回值为void。*/

ptr_to_func signal(int, ptr_to_func);

/* 它表示signal是一个函数,它接受两个参数,

其中一个是int,另一个是ptr_to_func,返回值是ptr_to_func。*/

然而,说到typedef就不能不说一下它的缺点。它同样具有其他声明一样的混乱语法,同样可以把几个声明器塞到一个声明中去。对于结构体,除了可以在书写时省掉struct关键字之外,typedef并不能提供显著的好处,而少些一个struct其实并没有多大帮助。在任何typedef声明中,甚至不必把typedef放在声明的开始位置。

typedef和#define的区别

typedef和define之间有一个关键性的区别。正确思考这个问题的方法就是把typedef看成是一种彻底的“封装”类型——在声明它之后不能再往里面增加别的东西。它和define的区别体现在两个方面:

1.可以用其他类型说明符对宏类型名进行扩展,但对typedef所定义的类型名却不能这样做。如下所示:

#define peach int

unsigned peach i ; //没有问题

typedef int banana;

unsigned banana i;//错误,非法

2.在连续几个变量的声明中,用typedef定义的类型能够保证声明中所有的变量均为同一种类型,而用#define定义的类型则无法保证。如下所示:

#define int_ptr int *

int_ptr chalk, cheese;

经过宏扩展,第二行变为:

int * chalk, cheese;

这使得chalk和cheese成为不同的类型:chalk是一个指向int的指针,而cheese则是一个int。

typedef char * char_ptr;

char_ptr Bentley, Rolls_Royce;

使用typedef定义的类型能够保证它们的类型相同,都是指向char的指针。

typedef struct foo{ ... foo;}的含义

C语言存在多种名字空间:

标签名(label name)。

标签(tag):这个名字空间用于所有的结构体、枚举和联合。

成员名:每个结构体或联合都有自身的名字空间。

其他。

在同一个名字空间里,任何名字必须具有唯一性,但在不同的名字空间里可以存在相同的名字。由于每个结构体或联合具有自己的名字空间,所以同一个名字可以出现在许多不同的结构内。有时可以看到这样的代码:

struct foo { int foo;} foo;

这显然会让将来维护这段代码的程序员感到困惑和沮丧,你说sizeof(foo)到底是表示哪个foo呢?

有些东西更加稀罕,像下面这样的声明竟然也是合法的:

typedef struct baz { int baz; } baz;

struct baz variable_1;

baz variable_2;

太多的“baz”了!让我们换一些清楚的名字,整理一下:

typedef struct my_tag { int i; } my_type;

struct my_tag variable_1;

my_type variable_2;

这个typedef声明引入了my_type这个名字作为"struct my_tag { int i; }"的简写形式。如果你用typedef声明一个标识符表示struct 结构类型,那么以后使用这个标识符时前面就不必加上关键字struct 了。但这个typedef声明同时也引入了结构标签my_tag,在它面前加个关键字struct可以表示同样的意思。

下面两个声明具有相似的形式:

typedef struct fruit { int weight , price_per_lb; } fruit; // 语句1

struct veg { int weight , price_per_lb; } veg; //语句2

但它们代表的意思却完全不一样,语句1声明了结构体标签”fruit“和由typedef声明的结构体类型”fruit“,其实际效果如下:

struct fruit mandarin; //使用结构体标签”fruit“

fruit mandarin; //使用结构体类型”fruit“

语句2声明了结构体标签”veg“和变量veg。只有结构体标签能够在以后的声明中使用,如:

struct veg potato;

如果试图使用veg cabbage这样的声明,将是一个错误。

使用typedef的一些提示:

1.不要在一个typedef中放入几个声明器,如下所示:

typedef int *ptr, (fun()), arr[5];

/* ptr是“指向int的指针”类型,

* fun是“指向返回值为int函数的指针”类型

* arr是“长度为5的int型数组”类型

*/

2.千万不要把typedef嵌到声明的中间部分,如下所示:

unsigned const long typedef int volatile *kumquat;

3.typedef为数据类型创建别名,而不是创建新的数据类型,可以对任何类型进行typedef声明。

typedef int (*array_ptr)[100];

4.应该只对所希望的变量类型进行typedef声明,为变量类型取一个喜欢的别名。关键字typedef应该如前所述出现声明的开始位置。在同一个代码块中,typedef引入的名字不能与其他标识符同名。

5.不要为了方便起见对结构体使用typedef。这样做唯一的好处是能使你不必书写”struct“关键字,但这个关键字可以向你提示一些信息,你不应该把它省掉。应该始终在结构体的定义中使用结构标签,即使它并非必须。这种做法可以使代码更为清晰。

6.typedef应该用在:

数组、结构体、指针以及函数的组合类型。

可移植类型。比如当你需要一种至少20bit的类型时,可以对它进行typedef操作。这样,当把代码移植到不同的平台时,要选择正确的类型如short,int,long时,只要在typedef中进行修改就可以了,无需对每一个声明都加以修改。

typedef也可以为后面的强制类型转换提供一个简单的名字,如:

typedef int (*ptr_to_int_fun)(void);

char * p;

...;

... = (ptr_to_int_fun) p;



推荐阅读
  • 题目概述:给定一个数组,计算其中所有连续子序列中平均值不低于给定值k的数量。通过将每个元素减去k并计算前缀和,问题转化为二维数点问题。此问题可以通过离线处理,利用树状数组来高效解决。 ... [详细]
  • A题简单判断#includeusingnamespacestd;typedeflonglongll;intt;intmain(){cint;whil ... [详细]
  • 本文档提供了数据结构在C语言中的实现示例,特别是解决二次方程的代码片段,以及《数据结构(用面向对象方法与C++语言描述)第二版》的部分习题答案。 ... [详细]
  • 本文旨在探讨Linux系统中两种重要的进程间通信(IPC)机制——System V和POSIX的标准及其特性,为开发者提供深入的理解。 ... [详细]
  • C++编程基础:探索自定义数据类型
    本文继续深入C++编程的基础知识,重点讲解自定义数据类型的概念及其应用,包括枚举类型、结构体和联合体等。 ... [详细]
  • 题目描述:孩子们围坐在一起,分享水果,场面温馨。然而,由于孩子们身高不同,排队时显得高低不齐。给定孩子们的身高序列,通过交换某些孩子的顺序,计算每次交换后的序列混乱度。 ... [详细]
  • VSCode中使用Clang-Format进行C/C++代码格式化配置
    本文介绍了如何在VSCode中配置Clang-Format以实现C/C++代码的自动格式化,包括安装必要的扩展、配置文件的创建以及常用设置的解释。建议阅读官方文档以获取更多详细信息。 ... [详细]
  • 探讨了一个关于Windows C++开发中遇到的乱码问题,特别是在处理宽字符时出现的情况。本文通过一个具体的示例——一个简单的窗口应用程序,展示了如何正确地使用宽字符以避免乱码。 ... [详细]
  • 本文详细介绍了Redis中对象的内部结构,包括数据类型、编码方式、最近访问时间(LRU)和引用计数等关键属性。通过这些属性,Redis能够高效地管理和优化内存使用。 ... [详细]
  • 双连通分量(biconnectedcomponent,简称bcc)概念:双连通分量有点双连通分量和边双连通分量两种。若一个无向图中的去掉任意一个节点( ... [详细]
  • 本文详细介绍如何在Android模拟器上安装TaintDroid的过程,包括解决源代码链接失效及服务器文件变动等问题,旨在帮助后续用户避免不必要的麻烦。 ... [详细]
  • 本文详细探讨了C语言中指针声明的语法及实际应用,通过具体的代码示例和解释,帮助开发者更好地理解和使用指针,特别是在复杂系统开发中的作用。 ... [详细]
  • 本文探讨了在多媒体软件开发中处理大型WAV音频文件的策略。由于Windows提供的`sndPlaySound` API仅适用于小文件,对于大型WAV文件,我们介绍了使用MCI(Media Control Interface)命令的一种有效解决方案。 ... [详细]
  • CUDA 技术旨在通过将大量计算任务分配给 GPU 来加速处理速度,从而节省时间。本文将探讨如何在 Linux 系统中使用 CUDA 查询设备(如显卡)的属性信息,包括但不限于内存分配和代码执行等关键参数。 ... [详细]
  • HidD_GetHidGuid(guidHID)hDevInfoSetupDiGetClassDevs(guidHID,0,0,DIGCF.DIGCF_PRESENTOrDIGCF ... [详细]
author-avatar
桃子小1992
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有