extern、struct等关键字

本文详细介绍了C语言中的extern、struct、union、enum、typedef等关键字的使用方法和特性,并对比了它们与#define的区别。extern用于声明外部变量和函数,struct可创建自定义数据类型,union提供数据共享空间,enum用于定义枚举类型,typedef则用于类型别名。文章还探讨了它们在不同场景下的最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最会帽子的关键字 - extern

image-20220621212708269

extern是专门用来声明变量和函数的关键字

当extern声明变量时,不可以初始化,也不可以省略。因为若是初始化的话,int n = 10就不是声明了而是定义,而定义是不能加extern的;若是省略extern的话,就无法清晰的知道int n究竟是定义了变量n无初始化,还是在声明n。

而extern声明函数时,是可以省略extern的,因为函数的定义是需要函数体的。而声明不需要,所以无论是否添加extern都可以清晰的知道该函数是在声明。但是为了和变量的声明具有统一性,所以函数的声明还是建议带上extern

struct关键字

空结构体多大

在vs2022中是不能够定义空结构体的

image-20220621213555203

而在Linux下可以定义空结构体,结构体大小为0

image-20220621214023243

其实,定义一个结构体,定义结构体时并不开辟内存,就相当于是制作了一个新的类型,用该类型创建变量时才会开辟内存。

结构体为空并无意义。vs2022直接禁止结构体为空,而Linux虽然可以定义空结构体,而我们也看到了该类型大小为0,用其类型创建变量时开辟的内存大小为0。

柔性数组

在c99标准下才存在柔性数组。

结构体的最后一个成员(成员数大于1)为未知大小的数组,该数组就是柔性数组.

image-20220621215109518

可以看到该结构体的大小是int的大小,所以并没有计算数组arr的大小。

数组arr其实是紧跟在结构体后面的

image-20220621220624842

image-20220621220832542

union关键字

image-20220621221424086

union称为联合或者是共用体,其大小为结构中最大的类型的大小。所以上面联合的大小为4,因为int大于char

而union结构中的所有的变量的地址都是相同的,是该联合的起始地址。

image-20220621221742640

联合的空间是所以结构成员公用的

image-20220621221922978

image-20220621222331155

image-20220621223438950

image-20220621223714255

enum关键字

枚举类型的使用方法

image-20220622212718518

enum类型的成员全都是常量,称为枚举常量,常量一般用全大写来表示,这些常量都是默认有数值大小的,默认从0开始。

而如果给这些常量赋予数值的话,就会从新数值开始往下递增。

image-20220622213052808

enum与#define的区别

  1. #define宏常量是在预编译阶段进行简单替换;枚举常量则是在编译的时候确定其值。
  2. 一般在调试器里,可以调试枚举常量,但是不能调试宏常量。
  3. 枚举可以一次定义大量相关的常量,而#define宏一次只能定义一个。

枚举能做到的事,#define能不能都做到?如果能,那为什么还需要枚举?

其实,#define是都能够做到的,但是若有很多个#define定义的宏,相互之间是没有任何相关性的,而用枚举则可以把这些具有相关性的集合起来。而且若有很多相关性的常量,如果用enum写的话还更简洁。

sizeof(enum类型)的值为多少?为什么?

image-20220622214335128

答案是4。

其实enum类型就跟int类型非常的相似。只不过enum是把具有相关性的常量集合起来了。

enum的成员全都是常量,且有默认的值,这些值都是int。

其实可近似的认为enum的成员就是int。

typedef

历史的误会 - 也许应该是typerename

typedef一般理解为重命名的意思

格式:typedef name rename

对一般类型typedef

image-20220623160335026

对结构体typedef

image-20220623160916877

对指针typedef

image-20220623161519584

对数组typedef

image-20220623161930773

typedef与#define的区别

看上面的例子,可以看到typedef与#define有很多相似的地方,但其实本质上是完全不同的。

typedef只能是对类型进行重命名,而#define可以对任意的符号进行”重命名“。

并且,#define的宏定义是符号的完全替换,而typedef则相当于是重新制作了一个与name相同作用的rename类型。

看下面例子,正常情况下的int* a, b, c;只有a是指针,其它都是整型,这是语法规定的,可以理解为*先与a结合了,就变成了int (*a), _b, _c,当然了括号是实际不存在的。而#define的宏定义则只是完全的符号替换,INT_P与int*只是模样不一样,但是其本质完全一样,所以看结果,_a是指针,其它还是整型。而typedef则完全不同,它则相当于是制作了一个新的类型,该类型的作用就是定义指针变量,该类型能作用于a_, b_, c_,所以这三者全都是指针。

image-20220623185148707

#define/typedef unsigned

对于typedef新的类型,编译器并不认识u_32 int的组合,所以改行报错而#define的完全替换,实际上还是unsigned int,所以改行不报错。

image-20220623190050072

#define/typedef int [10]

image-20220623191554155

#define是完全的字符替换,替换后就是int [10] arr1而语法中是不支持这样的。

typedef是把该数组的类型制作了下来,用该类型修饰arr2,则是完全没有问题的。

typedef static int s_int

image-20220623191850010

其实,typedef是存储类型的关键字。虽然看不出typedef与存储有什么关系。

出现该报错的原因是:存储关键字不可以同时出现,也就是说,在定义一个变量的同时,只能有一个存储关键字出现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

云朵c

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

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

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

打赏作者

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

抵扣说明:

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

余额充值