前言
通过指针,可以简化一些 C 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。
所以,想要成为一名优秀的 C 程序员,学习指针是很有必要的。
一、指针是什么?
指针是一个变量,它存储的是一个内存地址。
该内存地址指向另一个变量的位置,使得程序能够访问和操作该变量的值。
每一个变量都有一个内存地址,内存地址都可用 & 运算符取到内存地址
。
指针的声明使用 * 符号
// p 是一个指针变量,它存储了一个地址
// *p 是指针 p 所指向的地址上存储的值
int *p;
这个声明语句中,变量 p 是一个整数类型的指针。可以使用 & 符号获取一个变量的地址。
int n = 10;
int *p = &n;
这个语句中,&n 获取了变量 n 的地址,并将该地址赋给指针 p 。通过指针 p,可以访问和修改变量 n 的值。
*p = 20;
printf("%d", n); // 输出20
*这个语句中,p 表示指针 p 所指向的内存地址中存储的值。将 *p 赋值为 20 后,变量 n 的值也被修改为 20。
二、如何使用指针?
定义一个指针变量;
把变量地址赋值给指针;
访问指针变量中可用地址的值。
这些是通过使用一元运算符 * 来返回位于操作数所指定地址的变量的值。
1.指针的算术运算
- 指针的每一次
递增
,会指向下一个
元素的存储单元。 - 指针的每一次
递减
,会指向前一个
元素的存储单元。 - 指针在递增和递减时跳跃的字节数取决于
指针变量数据类型长度
,比如 int 就是 4 个字节。
递增一个指针
#include <stdio.h>
const int MAX = 3;
int main ()
{
int var[] = {
10, 100, 200};
int i, *ptr;
/* 指针中的数组地址 */
ptr = var;
for ( i = 0; i < MAX; i++)
{
printf("存储地址:var[%d] = %p\n", i, ptr );
printf("存储值:var[%d] = %d\n", i, *ptr );
/* 指向下一个位置 */
ptr++;
}
return 0;
}
// 存储地址:var[0] = e4a298cc
// 存储值:var[0] = 10
// 存储地址:var[1] = e4a298d0
// 存储值:var[1] = 100
// 存储地址:var[2] = e4a298d4
// 存储值:var[2] = 200
指针的比较
只要变量指针所指向的地址小于等于数组的最后一个元素的地址 &var[MAX - 1],则把变量指针进行递增。
#include <stdio.h>
const int MAX = 3;
int main ()
{
int var[] = {
10, 100, 200};
int i, *ptr;
/* 指针中第一个元素的地址*/
ptr = &var;
i = 0;
while ( ptr <= &var[MAX - 1] )
{
printf("存储地址:var[%d] = %p\n", i, ptr );
printf("存储值:var[%d] = %d\n", i, *ptr );
/* 指向下一个位置 */
ptr++;
i++;
}
return 0;
}
2.指针数组
ptr 声明为一个数组,由 MAX 个整数指针组成。
因此,ptr 中的每个元素,都是一个指向 int 值的指针。
int *ptr[MAX];
下面的实例用到了三个整数,它们将存储在一个指针数组中,如下所示:
#include <stdio.h>
const int MAX = 3;
int main ()
{
int var[] = {
10, 100, 200};
int i, *ptr[MAX];
for ( i = 0; i < MAX; i++)
{
ptr[i] = &var[i]; /* 赋值为整数的地址 */
}
return 0;
}
3.指向指针的指针
指向指针的指针是一种多级间接寻址的形式。当我们定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。
指向 int 类型指针的指针:
int a = 100;
int *p1 = &a;
int **p2 = &p1;
C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*。
p1 是一级指针,指向普通类型的数据,定义时有一个*;
p2 是二级指针,指向一级指针 p1,定义时有两个*。
4.传递指针给函数
#include <stdio.h>
void increment(int *ptr) {
(*ptr)++;
}
int main() {
int num = 5;
printf("Before increment: %d\n", num);
increment(&num);
printf("After increment: %d\n", num);
return 0;
}
5.从函数返回指针
// todo