目录
一、指针的基本概念和用法
二、指针运算
2.1 指针的自增和自减运算
2.2 指针的自增和自减运算
三、数组和指针
四、指针和函数
4.1 在函数中使用指针作为参数和返回值
4.1.1 使用指针作为函数参数
4.1.2 使用指针作为函数返回值
4.2 指针参数的传值和传引用特性
4.2.1 指针参数的传值特性
4.2.2 指针参数的传引用特性
嗨!我是Filotimo__。很高兴与大家相识,希望我的博客能对你有所帮助。
欢迎大家给我点赞、收藏⭐️,并在留言区与我互动,这些都是我前进的动力!
我的格言:森林草木都有自己认为对的角度。
在 C 语言中,指针是一个变量,用来存储一个地址,这个地址指向内存中的另外一个变量。可以通过指针来访问或修改这个变量的值。
使用 * 运算符可以访问指针所指向的变量的值。
使用 & 运算符可以获取变量的地址。
下面是一个使用指针访问变量地址和值的示例代码:
#include
int main() {
int num = 42; // 定义一个整数变量 num 并初始化为 42
int *ptr = # // 定义一个指针变量 ptr 并将其初始化为 num 的地址
printf("num 的地址是:%p\n", &num);
printf("ptr 所指向的地址是:%p\n", ptr);
printf("ptr 所指向的值是:%d\n", *ptr);
return 0;
}
输出结果如下:
在上面的示例代码中,我们首先定义了一个整型变量 num
并初始化赋值为 42
,然后定义一个整型指针变量 ptr
,并使用 &
运算符取 num
变量的地址初始化 ptr
指向 num
变量的地址。接着我们通过 printf
函数输出 num
变量的地址和 ptr
指向的地址,最后输出通过 *ptr
来访问 ptr
指向的变量 num
的值。
自增和自减运算仅适用于指向数组、字符串或分配内存的指针。
自增运算符
++
让指针指向下一个内存单元,即指针变量的值加上所指向的变量类型占用的字节数。自减运算符
--
让指针指向前一个内存单元,即指针变量的值减去所指向的变量类型占用的字节数。
示例代码:
#include
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int *p = &arr[0]; // 指向数组 arr 的第一个元素的指针
printf("当前指针 p 的值为: %p\n", p);
p++; // 指针自增操作
printf("执行 p++ 后,p 指向的值为: %d\n", *p);
p--; // 指针自减操作
printf("执行 p-- 后,p 指向的值为: %d\n", *p);
return 0;
}
输出结果如下:
这段代码中,我们定义了一个包含 5 个整型元素的数组 arr
,并定义一个指向数组第一个元素的指针 p
。通过执行 p++
和 p--
操作,指针 p
的值发生了变化,指向了数组中不同的元素,从而可以访问数组中不同的数据。
加法和减法运算可以应用于指向数组或分配内存的指针。如果对指针进行加法或减法运算,会根据指针所指向类型的字节大小来确定位移量。
指针的加法运算(+)将指针的值增加多个字节数。
指针的减法运算(-)将指针的值减去多个字节数。
示例代码:
#include
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *p = &arr[2]; // 指向数组 arr 的第三个元素的指针
printf("当前指针 p 的值为: %p\n", p);
p = p + 1; // 指针加法操作
printf("执行 p + 1 后,p 指向的值为: %d\n", *p);
p = p - 2; // 指针减法操作
printf("执行 p - 2 后,p 指向的值为: %d\n", *p);
return 0;
}
输出结果如下:
在这个示例中,我们定义了一个数组 arr
,并将指针 p
初始化为指向数组 arr
的第三个元素。通过执行 p + 1
和 p - 2
操作,指针 p
的值发生了相应的变化,通过访问指针 p
所指向的值,我们可以看到指针指向了数组中不同的元素。
数组名本身就是指向数组头部的指针。
例如,如果有一个 int 类型的数组 arr
,那么在代码中使用 arr
和 &arr[0]
是等效的,在内存中它们所指向的都是数组的第一个元素。
示例代码:
#include
int main() {
int arr[] = {1, 2, 3, 4, 5};
int *p = arr; // 指向数组 arr 的第一个元素的指针
printf("通过数组名访问数组的第一个元素:%d\n", arr[0]);
printf("通过指针访问数组的第二个元素:%d\n", *(p + 1));
printf("通过指针访问数组的第三个元素:%d\n", p[2]);
return 0;
}
输出结果如下:
可以通过将指针作为函数的参数来传递数据。这样可以实现在函数内部修改传递给函数的变量的值,因为指针传递的是变量的地址。
示例代码:
#include
void changeValue(int *ptr) {
*ptr = 10; // 修改指针指向的变量的值
}
int main() {
int num = 5;
printf("函数调用前的值:%d\n", num);
changeValue(&num); // 传递变量的地址
printf("函数调用后的值:%d\n", num);
return 0;
}
输出结果如下:
在这个示例中,我们在 changeValue
函数中使用了一个指针参数 ptr
,通过 *ptr
修改了变量 num
的值。在 main
函数中将 num
的地址传递给 changeValue
函数来实现修改 num
的值。
可以使用指针作为函数的返回值,以便将函数内部的计算结果返回给调用函数。
示例代码:
#include
#include // 包含 malloc 和 free 函数
int* createArray(int size) {
int *arr = (int*)malloc(size * sizeof(int)); // 动态分配内存,并强制类型转换
for (int i = 0; i < size; i++) {
arr[i] = i + 1;
}
return arr;
}
int main() {
int size = 5;
int *array = createArray(size); // 函数返回指针
for (int i = 0; i < size; i++) {
printf("%d ", array[i]);
}
free(array); // 释放内存
return 0;
}
输出结果如下:
在这个示例中,createArray
函数根据传入的参数 size
动态分配了一个整型数组,并将数组的首地址作为指针返回给调用函数。在 main
函数中,我们通过调用 createArray
函数来获取数组的地址,并使用指针 array
访问和输出数组的元素。最后,释放动态分配的内存。
当将指针作为函数参数进行传递时,实际上传递的是指针变量的值(即地址)。这意味着函数内部对指针本身的修改不会影响到调用该函数的代码。
示例代码:
#include
void changePointer(int *ptr) {
int dummy = 10;
ptr = &dummy; // 修改指针的值
}
int main() {
int num = 5;
int *ptr = #
printf("函数调用前的指针:%p\n", ptr);
changePointer(ptr);
printf("函数调用后的指针:%p\n", ptr);
return 0;
}
输出结果如下:
在这个示例中,changePointer
函数尝试将指针 ptr
指向一个新的变量 dummy
,但是在函数外部输出指针 ptr
的值时并未改变,验证了指针参数的传值特性。
通过使用指针的指针或者指针的引用,可以实现对指针的引用传递,从而在函数内部对指针进行修改可以影响到调用该函数的代码。
示例代码:
#include
void changePointer(int **ptr) {
int dummy = 10;
*ptr = &dummy; // 修改指针指向的地址
}
int main() {
int num = 5;
int *ptr = #
printf("函数调用前的指针:%p\n", ptr);
changePointer(&ptr);
printf("函数调用后的指针:%p\n", ptr);
return 0;
}
输出结果如下:
在这个示例中,我们将指针 ptr
的地址传递给 changePointer
函数,并在函数内部修改了指针 ptr
的值为新的变量 dummy
的地址。在函数外部输出指针 ptr
的值时发现已经改变,验证了指针参数的传引用特性。