【C语言】define&typedef详解

目录

1.前言

2.define详解

2.1define的简单替换

2.2 宏定义

2.3#号的作用

2.4##的用法

3.typedef详解

4.typedef相对于define的优势

5.结语


Hello everybody!最近我发现有很多宝子不能区分define和typedef的区别。所以这次咱们专门来讨论一下这个话题。希望大家阅读过我的文章后能够有所收获!

1.前言

这是我昨天看到的一个很有意思的题目,大家知道答案嘛?可以把自己的答案写在评论区。咱们先设置一个悬念,在本文的结尾我会公布答案\(0^◇^0)/

2.define详解

2.1define的简单替换

这就是define的一个简单的用法。意思是把int的含义赋给了INT,在下面编写代码时,可以用INT声明整型变量,也可以用int声明变量。在代码编写结束,运行代码时。c编译器会把INT全部替换成int。

注意在define定义结束后不要加分号,因为这时INT的含义就不是int了,而是int;

这样编写代码的话,程序有时不会出错,但很容易出错。咱们依然用刚才的例子:

加上分号后代码出错了,错误信息是a没有声明。有些宝子小小的内心却有了大大的疑惑:我明明用INT声明了a呀,怎么会呢?注意:这里INT的含义是int; 我们把INT用int;替换你就会发现问题的所在:

这是替换后的结果,哪里出错就一目了然了!

2.2 宏定义

宏定义类似于函数定义,也有类似于传参的过程。给大家举个栗子:

这段代码就是最简单的宏定义,在#define的语句中Add中的x,y相当于参数。在printf语句中,a相当于x,b相当于y。那么Add(a,b)就相当于a*b。

那如果我们要打印4*Add(a+1,b)的结果呢?有些宝子可能会觉得很简单呀,不就是4*((a+1)*b)嘛?如果这样算的话,结果就是880. 但事实却令人大跌眼镜:

结果居然只有60,与我们预期的880相差甚远!大家不要着急,请听我慢慢解释:

首先我们要知道,程序运行时是严格遵循我们所编写的代码的,所以在理解代码时要站在计算机的角度,万万不可主观臆断,平白无故的加上一些原本没有的符号,特别是括号!在Add(a+1,b)中,a+1相当于x,b相当于y。所以原式等价于a+1*b而不是(a+1)*b. 那么类似的4*Add(a+1,b)就等价于4*a+1*b而不是4*(a+1*b)。这就是60的来历。

那么如果我们想得到880怎么办呢?很简单,只需要加上两个括号就可以了。

看到这里,相信聪明的宝子们经过自己的思考应该有了自己的理解,我就不过多赘述了。

2.3#号的作用

注意这里的#不是#define和#include.那既然提到了,我也随便说一下叭:#define和#include属于预处理指令。在代码文件形成后缀为.exe的可执行程序时要经过的一个步骤叫预处理,这个过程会把define定义的符号全部换掉,例如上文中的INT,全部换成int

还要把include包含的头文件中的代码全部加进来。比如stdio.h 这个头文件比较大,有一万多行代码。

所以平时细心的宝子发现:自己编写的代码大小只有1KB,但是形成可执行程序后,它的大小变成了几百甚至几千KB.就是因为把头文件加进来了。

但我们今天讲的不是预处理指令,而是在编写代码中可能会用到的一个东西。

我们发现printf的参数有两个字符串的话也可以正常打印。知道这一点,接下来要讲的东西就更加容易理解一些。

这段代码看上去很简单,用了三个printf语句。但这样写显得代码有些冗余,我们能不能用宏定义的方式来简化代码呢? 当然可以!

这就是改进后的代码,printf的参数分为"the value of ", #n ," is ", format ,"\n" 和 n

大家可能不太理解的就是这个#n的含义。就是程序识别到#n时,会先把n用前面定义的参数替换掉,然后再加上双引号改成字符串。最终#n就被该成了"a","b","c".

大家以后在编写代码时,如果遇到需要多次使用printf语句时,当然可以试一试这种写法!

2.4##的用法

先说明一下,##基本上不用,在今后我们看到其他人用到这样的代码时,能看懂就行!

(符号一)##(符号二)。##的作用就是把符号一和符号二连结在一起。

3.typedef详解

这张图说明typedef是专门针对类型定义的,注意在typedef中要写分号,没有分号就会出现语法错误。

而define的定义就要灵活很多,可以用于类型定义,也可以定义其他的复杂结构,甚至是用一个符号代替一段代码!

这段代码是用ret来代替struct stu 这也是很常见的一种用法。

4.typedef相对于define的优势

通过上文,我们发现:define的功能确实比typedef要强大很多,但typedef也有自己的优势。这就回到本文开头我给出的那道题目了:

虽然这define中,INT_RTR的含义是int*,但它只是一个简单的替换,并没有把int*视为一种类型。这里的*与a视为一个整体。INT_PTR a,b;等价于int *a,b;说白了就是:int *a; int b;的组合。

而typedef int* int_ptr;中,虽然int_ptr的含义也是int*,但在这里程序把int*视为了一种指针类型。就是把int和*视为一个整体,那后面的c,d自然也是指针类型的变量。

讲解到这里,答案也就呼之欲出了:在变量a,b,c,d中 b不是指针类型的变量,其他都是!

5.结语

那么这一期的分享就到此结束了,希望大家在阅读过这篇文章后都能够收获满满。学习不是一蹴而就的,是在漫长的岁月中逐渐积累的。愿大家能都每天坚持学习,坚持敲代码,终有一天,你会从码农化身成为一名优秀的程序员!

当然,这篇文章如有表达不清晰或是逻辑错误的地方欢迎各位技术大佬指正!

  • 14
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

崽崽..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值