• extern、struct等关键字


    最会帽子的关键字 - 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与存储有什么关系。

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

  • 相关阅读:
    华为机试真题 Java 实现【最长广播响应】
    modelsim实现二选一以及D触发器并仿真
    Linux-进程、任务和作业管理
    R语言和医学统计学(13):协方差分析
    python-0006-django路由
    Linux命令ln -snf给文件创建软链接和硬链接
    二十八、高级IO与多路转接之select
    eBPF-4-perf_map的丢失事件lost_event解读
    【负载均衡式在线OJ项目day5】OJ服务模块概要
    Linux文件目录以及文件类型
  • 原文地址:https://blog.csdn.net/qq_67569905/article/details/125433581