学习笔记

指针

指针是 C 语言中可以直接访问内存的一种方式。通过指针操作,可以使得程序更加灵活。
指针变量中存储的是一个内存地址,通过使用操作符*来访问内存所指向的变量,&来获取变量所在的内存地址。

基本语法

声明:指向的变量类型* 指针变量名;。 如int* p;
让指针 p 指向变量 a : p = &a;
修改指针 p 所指向变量的地址: *p = 10。 (相当于a = 10;);

符号说明

int* 类型名,指向 int 型变量的指针。类似的还有char* double* float*等。
基础类型后面加 * 就代表声明的指针指向的是此基础类型的变量。这种存储指针的变量类型,每个变量所占字节数由系统位数决定。
现代计算机常见的是 64 位,即 8 字节。sizeof (int*)的计算结果为8

* 取目标值符,通过*指针的方式可以访问指针所指向的那个内存地址的实际数值,实际代表把正在操作的地址重定向到指针变量所指向的那个地址。
所以,*指针不只是代表所指向变量的值,还代表被指向该的变量本身
这允许我们直接使用*p = 10;来修改 p 所指向的变量本身。

& 取地址符,对一个变量使用&操作符可以获取到一个代表其地址的数值
&a可能获取到的值是0x7ffc014b7614,这个数字就代表其在内存中的位置。这也是指针变量所存储的内容。

注意事项

1.指针不要求必须指向一个变量,它可以指向数组,指向函数,甚至指向另一个指针。决定它指向什么的,取决于声明时的类型符。如(int[5])* p;就定义了一个指向长度为 5 的 int 数组的指针p。同样的,指针变量也不必为单个变量,它也可以是一个数组,记录一系列的地址。如int* p[5];就定义了一个长度为 5 的数组,每个元素都是一个指向 int 型变量的指针。

2.如果指针操作不当很容易产生野指针,即指针所指向的那个地址已经不被使用了,此时访问这个地址就会发生内存越界。因此野指针极其容易引起错误。所以当一个变量不需要使用时,需要将指向它的指针赋值NULL,变成空指针,以此避免潜在的内存越界危险。

结构体

结构是 C 语言中一种用户自定义的可用的数据类型,它允许存储不同类型的数据项。
结构体中的数据成员可以是基本数据类型(如 int、float、char 等),也可以是其他结构体类型、指针类型等。

基本语法

定义

struct tag {
    member_list
    member_list
    member_list 
    ...
} variable_list ;

tag 是结构体标签。
member_list 是标准的变量定义,比如 int i; 或者 float f;,或者其他有效的变量定义。
variable_list 结构变量,定义在结构的末尾,最后一个分号之前,允许指定一个或多个结构变量。

访问
为了访问结构的成员,我们使用成员访问运算符.
如有下列结构体:

struct book{
    char name[10];
    int page;
} mybook;

需要访问其成员page时,使用mybook.page来访问。

结构体指针
指针同样可以指向结构体。当需要访问指针所指向结构体的成员时,有两种选择可用。
假设指针p指向了mybook,如果需要访问成员page,有以下方法,
一是(*p).page,先p转换为指向的结构体,即(*p),再用成员访问运算符取得其成员。
二是直接用p->page,这相当于直接访问p所指向结构体的page成员。只有结构体指针才能使用->运算符!

符号说明

struct 结构体类型符,声明时使用,代表接下来声明的内容是一个结构体。

. 成员访问运算符,用于访问结构体中的成员。

-> 指针成员访问运算符,用于访问指针所指向的结构体中的成员。

注意事项

1.结构体里面的成员也可以是结构体。因此我们允许将不同的结构体嵌套,以实现更复杂的数据结构。

2.作为用户自定义的数据类型,结构体同样能作为参数传递给函数,只需在函数声明时写明参数类型的结构体即可。