[C语言]关键字解析(二) typedef和#define以及区别

这篇具有很好参考价值的文章主要介绍了[C语言]关键字解析(二) typedef和#define以及区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

typedef关键字

typedef关键字是type define的缩写,之前看一本书上说,也许这个关键字更应该叫typerename,我个人是比较认同的这个观点的.因为这个关键字只是给已有的类型重新定义了一个方便使用的别名,并没有产生新的数据类型。说直白点typedef就是类型重命名
在实际应用中typedef主要有如下几个应用

1 给基本数据类型定义新名字(两方面作用)

①使数据类型名称简洁:

typedef unsigned int UINT;//unsigened int略显冗余,所以重新命名为UNIT (此处结尾有分号;)
int main()
{
	UNIT a; //这里使用了自己重新命名的UNIT
	return 0;
}

②代码移植性
通过C语言的代码移植,运行在不同的平台上,使用typedef就可以定义与平台无关的类型。假如用户的程序代码用到了浮点类型,不同平台支持的最高精度不同,就可以用typedef重新直接定义一个的浮点类型,代码在不同平台运行时修改其定义即可.

//平台一:支持double的精度
typedef double decimal
//平台二:支持float的精度
typedef float decimal   //在不同平台修改decimal的内容即可 

2.给数组的类型重新命名一个新名字

typedef int arr[10];//这里arr就是一个整型数组类型名,当用户需要定义包含10个元素的整型数组时
int main()
{
	arr my_arr; //这里就等同于int my_arr[10]
	return 0;
}

3.给指针类型重新命名一个新名字

//一个经典问题:
//下面的p1,p2是什么类型
int main()
{
	int* p1,p2; //此时int旁边的*属于p1,并不属于p2,所以p1为整形指针,p2为整型
}
//现在换一种情况
typedef int * ptr_t; //typedef对int*整体进行了重命名
int main()
{
	ptr_t p1,p2; //此时ptr_t属于p1,也属于p2,所以p1,p2都是整型指针!!!
}
  1. 给自定义数据类型(结构体,枚举,共用体等)重命名一个新名字
typedef struct node
{
	char a;
	int data;
}stu,*pstu 
//这里在定义结构体数据类型时,利用typedef定义了两个类型,stu和pstu分别为普通变量类型和指向结构的指针类型。

总结:typedef虽然可以让一些基本数据类型和自定义数据类型变得简洁,但也不能大量使用,过度使用typedef可能会增加代码的复杂性。当定义大量的复杂的自定义类型别名时,理解代码可能会变得更加困难。所以要适当运用!

define关键字

在讲解这个关键字之前,想给大家看看一段略带诙谐的代码
[C语言]关键字解析(二) typedef和#define以及区别,c/c++,c语言,数据结构,算法

#define 叫做宏定义命令,是C语言预处理命令的一种.
宏定义就是用一个标识符来表示一个字符串,之后代码中出现了该标识符,就全部替换成指定的字符串.
因为只是简单替换,预处理程序对它不作任何检查,如有错误,只能在编译已被宏展开后的源程序时发现.

语法形式: #define name stuff (结尾无分号; 如果加上分号则连分号也一起替换)
#表示这是一条预处理命令,所有的预处理命令都以 # 开头。name是标识符的一种,命名规则和变量相同。stuff可以是数字、表达式、if 语句、函数等。

作用域:书写时必须在函数的外面,作用域为宏定义命令起到源程序结束(或者使用#undef)
宏定义的名字如果出现在引号之内,预处理程序不对其作宏代替

#define PI 3.14
int main()
{
	printf("%d",PI); //正常打印
	printf("PI"); //写在引号里,将不作宏替换,所以打印出来只是PI两个字母,而不是3.14
	return 0;
}
#undef PI
void func(){
    printf("%d",PI);//无法识别PI
}

带参数的#define

C语言允许宏带有参数。在宏定义中的参数称为“形式参数”,在宏调用中的参数称为“实际参数”。
比如下面这段代码

#define SQUARE(x)  x * x
int main()
{
	printf("%d",SQUARE(5));   //结果为25
	printf("%d",SQUARE(5+1)); //结果为11
	return 0;
}

第一个25相信很好理解,直接5×5=25,但是第二个为什么不是6×6=36.
原因在于宏只是一种简单的替换,所以在第二个例子中就被替换成了

printf("%d",5+1 * 5+1); //因为加减乘除的优先级,所以先算1*5,再分别+5再+1

所以用于对数值表达式进行求值的宏定义都应该用这种方式加上括号,避免在使用宏时由于参数中的操作符或邻近操作符之间不可预料的相互作用。

//改成如下形式
#define SQUARE(x)  (x) * (x)

注意: 在带参宏定义中,不会为形式参数分配内存,因此不必指明数据类型

看到这里相信大家也认为函数和带参数的宏有点相像,所以我将分析一下两者的区别
宏通常被应用于执行简单的运算

#define MAX(a, b) ((a)>(b)?(a):(b))  //比较两个数的大小

那为什么不用函数来完成这个任务?

  1. 用于调用函数和从函数返回的代码可能比实际执行这个小型计算工作所需要的时间更多。所以宏比函数在程序的规模和速度方面更胜一筹。
  2. 更为重要的是函数的参数必须声明为特定的类型。所以函数只能在类型合适的表达式上使用。反之这个宏怎可以适用于整形、长整型、浮点型等.形式上更加灵活

当然和函数相比宏也有劣势的地方:

  1. 每次使用宏的时候,一份宏定义的代码将插入到程序中。除非宏比较短,否则可能大幅度增加程序的长度。
  2. 宏是没法调试的。
  3. 宏可能会带来运算符优先级的问题,导致程容易出现错误

宏有时候可以做函数做不到的事情。比如:宏的参数可以出现类型,但是函数做不到

#define MALLOC(num, type)  (type *)malloc(num * sizeof(type))

//在函数中使用时
MALLOC(10, int);//此处int类型就作为了参数之一
//预处理器替换之后:
(int *)malloc(10 * sizeof(int));

typedef和#define区别

最后,我们应该注意用宏定义表示数据类型和用 typedef 定义数据说明符的区别。

宏定义只是简单的字符串替换,在预处理阶段由预处理器来处理;而 typedef 是在编译阶段由编译器处理的,它并不是简单的字符串替换,而给原有的数据类型起一个新的名字,将它作为一种新的数据类型。文章来源地址https://www.toymoban.com/news/detail-695311.html

到了这里,关于[C语言]关键字解析(二) typedef和#define以及区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 初识C语言中的typedef、define以及Status

    小阿杰最近开始看数据结构啦嘿嘿嘿, 可惜小阿杰C语言功底稀薄,以此篇随笔记录一下我卑微的学习之路/苦涩/苦涩 首先define没啥好说的,在文件开头,定义一个固定不变的值。  然后顺便提一嘴 const(写着博客突然想起来有这么个玩意👉👈) const 叫 常量限定符,一般他出

    2024年02月16日
    浏览(9)
  • 搜索引擎优化指南:SEO关键字、长尾关键字、短尾关键字以及反向链接

    SEO 代表“搜索引擎优化”。它是一种数字营销策略,旨在提高网站或网页在搜索引擎未付费结果中的在线可见性。通常,网站在搜索结果页面中排名越高,或在搜索结果列表中显示的频率越高,它将从搜索引擎用户那里获得的访问者就越多。 SEO 策略可以针对各种类型的搜索

    2024年02月04日
    浏览(254)
  • Java面向对象——多态、Object类、instanceof关键字以及final关键字

    Java面向对象——多态、Object类、instanceof关键字以及final关键字

    总之,多态是面向对象编程中一个非常重要的概念,通过它可以实现统一的接口来操作不同的对象,提高代码的可读性和可维护性。在实际编程中,多态性的使用可以使代码更加灵活和扩展性更强。方法重写是实现多态的基础。 重写如下所示 关于hashCode方法的重写: 重写t

    2024年02月12日
    浏览(48)
  • Java关键字:final解析

    目录 一、final变量 二、final方法  三、final类 final是Java语言中的一个,凡是被final修饰过的内容都是不可改变的。 final可用于变量声明,一旦该变量被设定,就不可以再改变该变量的值。通常,由final定义的变量为常量。 final double PI = 3.14 final定义的

    2024年02月14日
    浏览(42)
  • Mysql关键字执行顺序-深入解析

    Mysql关键字执行顺序-深入解析

    mysql执行顺序如下: 这些涉及的sql笔者这里就不一一去写了。 Mysql会先执行from,然后根据on去筛选目标表,筛选出的结果再进行join或者using,这样就会形成一个临时表。然后去执行where条件去筛选这个临时表,这样基本就筛选出需要的数据了。然后就可以

    2023年04月22日
    浏览(11)
  • java面向对象——继承以及super关键字

    java面向对象——继承以及super关键字

    在 同⼀类 中,存在⽅法名相同,参数列表不同(个数、类型或顺序不同)的⽅法互为重载。 在 继承关系 中,⼦类声明⼀个继承⾃⽗类的⽅法名相同、参数列表相同,返回值类型⼀致,访问修饰符相同或 变⼤,抛出异常相同或缩⼩的⽅法称为重写。 重载是编译时多态,重写

    2024年02月12日
    浏览(8)
  • C语言volatile关键字

    在C语言中, volatile 是一个类型修饰符,用于告诉编译器对象的值可能会在编译器无法检测到的情况下被改变。这通常发生在以下两种情况: 硬件的输入/输出操作,例如一个设备寄存器的读取或写入。 共享内存的并行程序,其中一个线程修改了一个内存位置,而另一个线程

    2024年02月07日
    浏览(14)
  • 【C语言】for 关键字

    【C语言】for 关键字

    🚩WRITE IN FRONT🚩    🔎介绍:\\\"謓泽\\\"正在路上朝着\\\"攻城狮\\\"方向\\\"前进四\\\"🔎 🏅荣誉:2021|2022年度博客之星物联网与嵌入式开发TOP5|TOP4、2021|2022博客之星TOP100|TOP63、阿里云专家博主、掘金优秀创作者、全网粉丝量5w+、全网访问量70w+🏅 🆔本文章内容由 謓泽 原创 如需相关转载

    2023年04月17日
    浏览(22)
  • 【C语言】static关键字详解

    【C语言】static关键字详解

    目录 1.static是什么? 2.static修饰的对象是? 3.static修饰后改变了什么? 4.static修饰操作演示 (1) 局部变量 如果加了static修饰局部变量i会怎么样? 全局区(静态区) (2) 全局变量 如果给全局变量加上了static修饰呢? 二者区别?  这样用有什么用? (3) 函数 5.总结

    2024年02月10日
    浏览(13)
  • C语言-外部关键字extern

    C语言-外部关键字extern

    extern  extern 用在全局变量或函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用。  什么是定义,什么是声明?       什么是定义:所谓的定义就是为这个变量分配一块内存并给它取上一个名字,这个名字就是我们经常所说的变量名。但注意,这个名

    2024年02月07日
    浏览(11)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包