==初版有很多知识点深奥,还没来得及整理完成。==
1.指针的基本概念
指针的定义:
指针是一个变量,它存储的是另一个变量的内存地址(带类型的地址:不同的类型占的内存地址不一样:int一般占4个字节)
指针与变量之间的关系:
指针和变量都是存储在内存中的实体。变量存储的是数据值,而指针存储的是数据值的地址。通过指针,我们可以间接地访问和操作变量的值。
指针的声明与初始化
声明:
**数据类型 *名字
**:int *a;
初始化:名字 = 地址
:a = &b
(其中a与b的数据类型要一致)
取地址运算符&:是一个一元运算符,写在一个数据对象的左边,可以获取一个数据对象的首地址和所需存 储空间大小。
取值运算符*:
取值运算符是一个一元运算符,写在一个指针的左边,可以根据指针中存储的首地址和空间大小找到目标数据对象
1 | int n = 123; |
2.指针的基本操作
指针的运算
整形与指针类型的加减
作用:实现指针的移动,并未改变指针的值
+n: 指针类型+1后,将首地址
向
后移动了 sizeof(目标数据对象) 字 节。-n:指针类型-1后,将首地址向
前
移动了 sizeof(目标数据对象) 字 节。- sizeof(目标数据对象) 被称作步长
同类型指针类型的相减
作用:计算数组元素个数:通过指向数组首元素和尾元素的指针相减,可以快速得到数组的元素个数。
- 结果为两首地址的差值除以步长
3.指针与数组
1,数组名作为指针
数组名可以被当作指向其第一个元素的指针。
2,数组元素的访问
1 | int element1 = arr[2]; // 索引访问,等同于 *(arr + 2) |
3, 指针运算与数组
指针运算(如加法、减法)与数组紧密相关。例如,给指针加上一个整数n,相当于将指针向前移动n个元素(每个元素的大小由指针类型决定)。这常用于遍历数组:
1 | for (int *p = arr; p < arr + 5; ++p) { |
4, 数组传递给函数
当数组作为参数传递给函数时,实际上传递的是指向数组第一个元素的指针。因此,在函数内部,我们无法知道数组的实际大小,但我们可以访问数组的元素:
1 | void print_array(int *arr, int size) { |
4.多级指针指针数组
特别篇:指针数组与数组指针
- 指向数组的指针(数组指针):通常用于表示固定大小的多维数组。例如,
int (*ptr)[cols]
是一个指向有cols
个整数的数组的指针。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main() {
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
int (*ptr)[4] = arr; // ptr指向一个包含4个整数的数组
// 访问数组元素
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", (*ptr)[i * 4 + j]); // 复杂,不推荐这样使用
printf("%d ", ptr[i][j]); // 推荐使用这种方式
}
printf("\n");
}
return 0;
} - 指针数组:是一个数组,其元素是指针。它可以用于存储多个指向不同类型或相同类型数据的指针。例如,
int *ptrs[size]
是一个有size
个int *
类型元素的数组。1
2
3
4
5
6
7
8
9
10
11
12
13
int main() {
int a = 1, b = 2, c = 3;
int *ptrs[3] = {&a, &b, &c}; // ptrs是一个指针数组,存储三个int指针
// 访问指针指向的值
for (int i = 0; i < 3; i++) {
printf("%d ", *ptrs[i]);
}
return 0;
}
5.指针与函数
1. 函数指针
2. 指针作为函数参数
函数可以接受指针作为参数,这使得函数能够直接访问和操作指针所指向的数据。这种能力在处理数组、字符串以及动态分配的内存时尤为重要。
1 |
|
3. 指针作为函数返回值
4. 修改函数外部的变量
6.指针与字符串
字符串与字符数组
在C语言中,字符串是以字符数组的形式存储的,并且以空字符(’\0’)作为结尾标志。例如:
1 | char str[] = "Hello, world!"; // 字符数组初始化字符串 |
1.字符串名作为指针
在C语言中,当你声明一个字符数组并初始化为一个字符串时,字符串名(即数组名)可以作为一个指向该字符串首字符的指针来使用。例如:
1 | char str[] = "Hello, world!"; |
2.字符指针与字符串字面量
除了字符数组之外,字符串还可以以字符串字面量的形式出现。字符串字面量是一个常量字符数组,存储在程序的只读数据段中。当你将一个字符串字面量赋值给一个字符指针时,你实际上是在让这个指针指向字符串字面量的首字符。例如:
1 | char *ptr = "Hello, world!"; // 字符指针指向字符串字面量 |
3.修改字符串
如果你需要修改字符串的内容,你应该使用字符数组而不是字符指针指向的字符串字面量。因为字符串字面量是只读的,尝试修改它们会导致未定义的行为(通常是程序崩溃)。
1 | char str[] = "Hello, world!"; // 字符数组,可以修改 |
7.**动态内存分配与指向它的指针变量(不太会)
8.指针的注意事项
1.空指针(NULL指针):
- 在声明指针变量后,如果没有初始化,它将包含一个不确定的值(垃圾值),这可能导致未定义的行为。因此,通常建议将指针初始化为
NULL
,表示它不指向任何有效的内存位置。 - 在使用指针之前,始终检查它是否为
NULL
,以避免尝试访问无效的内存地址。
2.指针运算
- 指针运算(如递增、递减、加法、减法)在C语言中很常见,但必须谨慎使用。指针运算的结果必须指向有效的内存区域,否则可能导致未定义的行为。
3.指针类型
指针的类型决定了它所指向的内存的大小和解释方式。将一种类型的指针强制转换为另一种类型(类型转换或强制类型转换)可能会导致不可预测的结果,