C语言中typedef和const的区别

news/2024/7/5 2:52:12

昨天面试的时候面试官问了这个问题,平时也有见过这两个类型限定词,可能是因为不怎么使用的原因,当问到它们的区别时,我不知道从哪个方面开始回答。

用 typedef 定义新的类型名

类型定义的书写格式为

typedef 类型 被定义的类型名

被定义类型名通常用大写字母构成。从语法形式上看,typedef出现在“类型”的左边,类似于 extern、static 等存储类区分符在说明中所占的位置,实际上typedef不保留存储空间,只是为了语法上方便,才称它为“存储类区分符”。

typedef char *STRING;

typedef int MILES, *SP, (*PF)();

显然,MILES与int同义,而SP与指向int型的指针同义,STRING与字符指针同义,PF与指向函数(返回int型)的指针同义。

必须强调,typedef说明并不产生新的类型,只是给已有的类型添加新的类型名,或者说以另一种方式来指出类型而已。使用这种方式说明的变量与关键字明确指出类型的那些变量具有同样的性质。

使用typedef说明的主要原因有两个:

1. 使说明便于理解。用这种类型定义方式,使指向复杂结构的指针的说明方式简洁明了。

2. 将程序参数化,以便移植。若typedef用在与机器有关的数据类型中,当程序移植时,只要改变typedef就可以了。通常情况是对不同的整数量使用typedef所产生的名,因而每个宿主机能够挑选出与short、int和logn适应的集合。

最终,将来总可以让编译程序或其它程序(如lint),用typedef说明中的信息来对程序进行附加的检查。

这里说的是不是在debug的时候,可以通过typedef定义的变量名,更方便找到问题出现的位置。

类型限定词

C语言中有两个关键字称为类型限定词:const和volatile。前者将对象限定为常量,后者将对象限定为易变量。

类型限定词的书写位置在类型名(即类型区分符)之首,当有存储类区分符时,声明中各词的次序可为:

类型限定词 存储类区分符 标识符

存储类区分符 类型限定词 标识符

被const限定的对象,在一次定值后,不允许再赋值或增量、减量。

需要注意C语言中const的用法与PASCAL中的const不完全相同,其特点是:

1. 类型限定词的作用在遇到分号时就停止了。

2. 聚集类型的规格说明中也可以包含限定词,如下面的标识符a就被限定为数组常量名:

typedef int AT[2][3]; /* AT是2行3列的整数型数组名 */
const AT a = {{4, 5, 6}, {7, 8, 9}}; /* a是AT型数组,其元素是const int型 */

3. 为使两个限定类型相容,则二者都应为相容类型的完全相同的限定形式。因此若在以上声明中增添下列两条:

int *pi;
const int *pci;

则语句 pci = &(a[0][1]); 是有效的,而语句 pi = &(a[0][1]); 无效,因为等号两边的类型不匹配。不过有些编译器并未严格按照C语言标准去实现。因此,语句 pi = &(a[0][1]); 仍可能通过编译。

4. 如果对程序中的一些变量,人们不希望编译器对它的计算顺序进行任何优化或重新排序,则在声明时应当用限定词 volatile 进行约束。这在描述对应于存储映射的输入输出端口的对象,或由异步中断函数访问的对象时经常用到,如:

extern const volatile int real.time.clock;

则 real.time.clock可被硬件在程序员不确切知道的情况下进行修改,但编译器不会对它进行计算顺序的变更。

5. 同一对象可以受两个不同限定词的约束,例如声明为

extern const volatile int real.time.clock;

的对象,除了(4)中的叙述特点外,还受不能被赋值,增量或减量的限制。

内部函数与外部函数

对于比较大的程序,通常分放在多个源文件中,也称为多源文件(multy files)。因为每个文件是一个编译单元,于是修改某个源文件时不必重新编译其它的源文件。这种文件结构还便于多人分别编写与调试程序。采用多文件结构时,对各个文件中的变量与函数的定义与使用应当相互协调,这不仅涉及到正确运用变量的存储类,还要掌握内部函数等概念。

1. 内部函数

内部函数只能被本程序文件中其他函数所调用。内部函数的定义方法是在函数的类型前加static,即:

static 类型标识符 函数名(数据类型 形式参数1, 数据类型 形式参数2, ...) {

         函数体       

}

内部函数又称静态函数。使用内部函数可以使函数只局限于所在文件,即不同的文件中有相同函数名的函数也不会相互干扰。这在多人同时编写一个程序的不同部分的时候特别有用。通常把只由同一文件使用的函数和外部变量放在一个文件中,用static加以说明使之局部化,限制其他文件对其引用。

2. 外部函数

外部函数的定义方法是在函数的类型标识符名前加extern,即

extern 类型标识符 函数名(数据类型 形式参数1,数据类型 形式参数2,...){

        函数体

}

如果在定义函数时省略extern,则默认为外部函数。在需要调用此函数的文件中对此函数进行原型声明时,一般也要用extern来说明所调用的函数是在其他文件中定义的外部函数。


http://lihuaxi.xjx100.cn/news/1504463.html

相关文章

onnx模型修改:将均值和方差放到模型中

训练模型时,一般都会对原始数据进行归一化再送入网络,即减均值和除方差。在部署时,我们也要进行同样的操作。有些推理框架会提供对应的接口,我们只需要设置均值和方差即可,如MNN.也有一些框架不提供这样的功能&#xf…

Matlab怎么引入外部的latex包?Matlab怎么使用特殊字符?

Matlab怎么引入外部的latex包?Matlab怎么使用特殊字符? Matlab怎么使用特殊字符?一种是使用latex方式,Matlab支持基本的Latex字符【这里】,但一些字符需要依赖外部的包,例如“𝔼”,需…

MySQL8.0.28数据库在windows版本下运行宕机问题解决

问题描述 MySQL8.0.28数据库在windows2022服务器上运行,使用Navicat执行数据备份或者是在并发量较高的情况下会自行宕机,查看日志后发现报错问题如下: mysqld got exception 0x16 ; Most likely, you have hit a bug, but this error can a…

Pipeline Stages

Use of Pipeline Stages in the Compactor Pipeline stages有时能够通过提高扫描移位频率来提高数据通过compactor中逻辑的整体速率。pipeline stages是通过logic level保持中间值输出的寄存器,所以进入logic level中的值可能在一个时钟周期中更早地更新。因为EDT逻辑逻辑级数…

C++进阶之多态

多态 多态的概念多态的定义及实现1.多态的构成条件2.虚函数3.虚函数的重写4.虚函数重写的两个例外5.C11 override 和 final6.重载、覆盖(重写)、隐藏(重定义)的对比 抽象类1.概念2.接口继承和实现继承 多态的原理1.虚函数表2.多态的原理3.动态绑定与静态绑定 单继承和多继承关系…

《来往拜访》的隐私政策

本应用尊重并保护所有使用服务用户的个人隐私权。为了给您提供更准确、更有个性化的服务,本应用会按照本隐私权政策的规定使用和披露您的个人信息。但本应用将以高度的勤勉、审慎义务对待这些信息。除本隐私权政策另有规定外,在未征得您事先许可的情况下…

权限管理 ACL、RBAC、ABAC的学习

ACL(Access Control List:访问控制列表) 最简单的一种方式,将权限直接与用户或用户组相关联,管理员直接给用户授予某些权限即可。 这种模型适用于小型和简单系统,权限一块较为简单,并且角色和权限的变化较少。 RBAC(R…

【C++】C++11新特性 lambda表达式

C11新特性 lambda表达式1、引入2、lambda表达式语法3、 捕获列表说明4、 lambda表达式的原理5、 lambda对象的大小 lambda表达式 1、引入 在C98中,如果想要对一个数据集合中的元素进行排序,可以使用std::sort方法,如果待排序元素为自定义类…