petard  

第 12 章 指针 pointer

12.6 多级指针

指向指针的指针称为多级指针

eg:int *ptr1 = #
	int **ptr2 = &ptr1;
	int ***ptr3 = &ptr2;

12.7 空指针

应用场景:
1. 暂时不确定指向的指针,可以在定义的时候先赋值为NULL
2. 有些指针函数,如果内部出现异常无法成功实现功能,可以返回NULL

eg: int *ptr1 = NULL; double *ptr2 = NULL; short (*ptr3)[] = NULL;
	time_t n = time(NULL);

注意事项:空指针 不允许解引用。

12.8 野指针

产生野指针的场景:
1. 未初始化的指针
2. 越界的指针
3. 指向的被销毁的数据

要避免野指针!

总结

1. 指向普通变量的指针
int *、double *、char *、short * .....

2. 指针和数组
int *[]   指针数组
int (*)[] 数组指针

3. 指针和函数
double *(int,int)   指针函数
double (*)(int,int) 函数指针

4. 多级指针
double *** 、 int **

第 13 章 自定义数据类型

C 语言数据类型总结:

整型: char、short、int、long、long long

浮点型:float、double、long double

数组: int []double [10]int[2][3] ...

函数:double (int,int)void () ...

指针:int *double *double (*)[]int (*)(int,int,int) ...

自定义枚举类型

自定义结构体类型

自定义共用体类型

13.1 枚举 enum

① 定义枚举类型

enum 枚举类型名称
{
    枚举元素名称1,
    枚举元素名称2,
    枚举元素名称3
    ...
}

注:

  1. 枚举类型名称 和 枚举元素名称 都需要符合标识符规范
  2. 枚举元素也称为枚举常量、枚举成员、枚举列表项 等,其本质就是一个标识符常量

② 根据 枚举类型 定义 枚举变量

1. 先定义枚举类型,再定义枚举变量
2. 同时定义 枚举类型 和 枚举变量
3. 同时定义 枚举类型 和 枚举变量,并将枚举类型省略
  • 用格式化字符用 %d
  • 枚举元素都是常量
  • 如给枚举变量重新赋值 枚举元素意外的 元素,不推荐这样赋值
  • 可以 printf 直接打印输出 枚举元素的值?

③ 枚举元素的特点

(1)枚举元素的值必须在同一枚举中是【唯一】的
(2)枚举元素的值必须是【整数类型】,通常是int
(3)如果没有为枚举元素指定值,编译器会自动为它们分配值,从0开始,依次递增。
	若只给枚举类型的第一元素赋值为2,后面的元素也会在2的基础上依次递增1的;
	枚举类型的每个元素都可以被赋值,不过必须是整型
(4)定义枚举的时候也可以为枚举元素自定义值,需保证【唯一性】和【整型类型】。——1、2点的结合

13.2 结构体 struct

① 定义结构体类型

struct 类型名称
{
    成员类型 成员名称1;
    成员类型 成员名称2;
    成员类型 成员名称3;
   ...
}

注:1、结构体类型名称 和 成员名称 都需要符合标识符规范。

​ 2、

        struct 类型名称
        {
            char *name;		// 未初始化,只分配存放地址的内存 没有分配存放字符串的地址;
            char name[100]; // 所以当需要存放字符串时,声明用字符串数组,不要用指针
        }

② 根据 结构体类型 定义 结构体变量

1. 定义结构体变量
   ① 先定义 结构体类型 ,再定义 结构体变量
   ② 同时定义 结构体类型 和 结构体变量
   ③ 同时定义 结构体类型 和 结构体变量,并省略 结构体类型 的名称
   
2. 结构体变量的 初始化
   ① 先【声明】结构体变量,然后挨个给成员【初始化赋值】
   ② 在声明结构体变量的同时,使用 {} 一次性给成员初始化赋值
   
3. 访问结构体变量的成员
   使用 . 运算符  ————?
   结构体变量名.成员名

函数形参为结构体:void printStudentInfo(struct Student stu)

strcpy (stu1.address, "中国"); ——把 中国 复制给 stu1.address

③ 结构体指针

1.声明结构体指针 语法格式:
    struct 结构体名 *结构体指针变量名;

2.结构体指针访问成员:
    结构体指针可以通过“->” 操作符访问结构体的成员。
    
	指针名->成员名 与 变量名.成员 是等价的
    	变量名.成员——指的是该成员的存放地址
    
    如果指针变量p指向一个结构体变量stu,以下3种用法等价:
        (1)stu.成员名
        (2)(*p).成员名
        (3)p->成员名

eg: struct Student *stu_ptr = &stu;
	// 通过结构体指针,给里面的成员 重新赋值
    stu_ptr->age = 18;		// (*stu_ptr)—>age = 18;
    stu.id = 102;
	// 解引用结构体指针,并重新给对应成员 赋值
    (*stu_ptr).name = "司马懿";

  • sprintf(),用于将格式化数据写入字符串

④ 结构体变量的存储大小

1. 类型对齐 		——以空间换时间
   变量的地址一定是【数据类型长度】的【整数倍】,如 int 类型变量它的地址一定是 4 的倍数
 
2. 结构体对齐
   ① 结构体成员对齐: 【结构体成员地址】的相对于【结构体地址的偏移量】,肯定是自身类型长度的【整数倍】
   ② 结构体整体对齐: 结构体存储大小 肯定是【结构体基准长度】的整数倍,结构体以 基准长度 为对齐单位。
                   大部分情况下,基准长度是最大成员的长度。		
                   		——目前 基准长度 大部分都是16个字节,也就是目前数组类型的最大长度值
                   		——相对于单片机,会有4字节的,一般会 基准长度 和 最大成员的长度比较,取较小值
   ③ 自行设置结构体基准长度  #pragma pack(长度) 		——放在需要设置的结构体上面就行,不需要放在最顶部头文件处


3. 结算结构体变量存储大小的语句:
	printf("%zu \n", sizeof(结构体类型));  // 结构体类型如:struct User

总结

  1. 枚举 enum
  2. 结构体 struct
    2.1 定义结构体(类型)
    2.2 定义结构体变量
    2.3 结构体指针(指向结构体变量)
    2.4 结构体存储大小(内存对齐)
posted on 2024-04-12 21:16  岌岌无名  阅读(6)  评论(0编辑  收藏  举报