C语言指针及其主要应用详解

"指针"是C语言中非常重要的一个特性,但我在第一次学习指针时感到非常难以理解,不光概念很抽象,也不知道学习它有什么用,这篇文章我会用我的理解讲述"指针"及其主要应用。

一.指针是什么?

指针就是存储内存地址的变量。让我们用一个生动的比喻:

把计算机内存想象成一个巨大的旅馆,每个房间都有唯一的门牌号(内存地址),而指针就是记录这些门牌号的便签

c 复制代码
int *p;     // 指向整数的指针
char *c;    // 指向字符的指针  
float *f;   // 指向浮点数的指针

二.两个关键运算符

1.取地址运算符&

获取变量的内存地址

2.解引用运算符*

c 复制代码
int main() {
    int num = 10;
    int *p = #     // p存储num的地址
    
    printf("num的值: %d\n", num);      // 输出: 10
    printf("num的地址: %p\n", &num);   // 输出地址(eg:000000000065FE44)
    printf("指针p的值: %p\n", p);      // 输出地址(与&num相同)
    printf("通过p访问的值: %d\n", *p); // 输出: 10
    
    return 0;
}

三.指针与数组的紧密关系

c 复制代码
int arr[3] = {10, 20, 30};

注意:数组名在大多数情况下会自动转换为指向首元素的指针

c 复制代码
printf("arr:      %p\n", arr);        // 数组首元素地址
printf("&arr[0]:  %p\n", &arr[0]);    // 第一个元素的地址

// 输出结果:arr和&arr[0]的值相同

但要注意它们的类型不同

  • arr 的类型是 int[3] (数组类型)
  • &arr[0]的类型是int*(整型指针)

指针如何访问数组元素

c 复制代码
int arr[3] = {10, 20, 30};
int *p = arr;  // p指向数组首元素

printf("%d\n", arr[1]);   // 20
printf("%d\n", *(p+1));   // 20  
printf("%d\n", p[1]);     // 20

我在学习时遇到的一些困惑

1.指针存储的是整个数组 吗?

不是,int p = arr;不是把整个数组赋给p,而是把数组的首元素的地址赋给指针p(再学习数组时有讲到,但我在第一次看到这行代码的时候混淆了,所以提一下)

2.为什么p[1]能输出第二个元素?

这是由于 指针的算术运算,在指针中 p[1]等价于 *(p+1),即p[1]不是访问p指向的内容,而是访问"从p开始第1个位置"的内容

详细分解:

  • p+1:指针向前移动1个int大小的距离(通常时4个字节)
  • *(p+1):取那个地址的值
  • 得到arr[1]的值:20

四.为什么需要指针?

1.函数参数传递 - 修改原值

在调用函数时,函数内部为形参,在函数内部的操作并不会影响实参

c 复制代码
//修改分数

#include <stdio.h>

// 错误:无法修改原值
void addScore_wrong(int score) {
    score += 10;
}

// 正确:使用指针修改原值
void addScore_correct(int *score) {
    *score += 10;
}

int main() {
    int myScore = 80;
    
    printf("原始分数: %d\n", myScore);
    
    addScore_wrong(myScore);
    printf("错误方法后: %d (没变化!)\n", myScore);
    
    addScore_correct(&myScore);
    printf("正确方法后: %d (加了10分!)\n", myScore);
    
    return 0;
}

//输出:
//原始分数:80
//错误方法后:80(没变化)
//正确方法后:90(加了10分)

2.返回多个值

在调用函数时,如果仅仅使用return返回值,那么只能返回一个值,但利用指针,可以返回多个值

c 复制代码
//计算长方形的面积和周长
#include <stdio.h>

// 通过指针返回多个值
void calculateRectangle(int length, int width, int *area, int *perimeter) {
    *area = length * width;        // 面积
    *perimeter = 2 * (length + width); // 周长
}

int main() {
    int len = 5, wid = 3;
    int area, perimeter;
    
    calculateRectangle(len, wid, &area, &perimeter);
    
    printf("长方形: 长=%d, 宽=%d\n", len, wid);
    printf("面积: %d\n", area);
    printf("周长: %d\n", perimeter);
    
    return 0;
}

//输出
//长方形:长=5,宽=3
//面积:15
//周长:16

在后续的学习中我会进行补充

相关推荐
UIUV2 天前
JavaScript中的LHS和RHS查询机制详解
前端·javascript·代码规范
San302 天前
Trae Que:用智能提示词提升编程效率的新范式
javascript·人工智能·代码规范
Hilaku3 天前
别再吹性能优化了:你的应用卡顿,纯粹是因为产品设计烂🤷‍♂️
前端·javascript·代码规范
奋进的电子工程师4 天前
如何实现开源组件的安全与合规治理?
安全·开源·代码规范·设计规范·代码复审
San30.5 天前
从代码规范到 AI Agent:现代前端开发的智能化演进
javascript·人工智能·代码规范
IT界的奇葩5 天前
代码规范 spring-javaformat使用
java·spring·代码规范
花生Peadar5 天前
AI编程从入门到精通
前端·后端·代码规范
jump_jump6 天前
Claude vs Doubao Seek Code 产码能力对比
ai编程·claude·代码规范
千桐科技8 天前
数据库设计最佳实践:我们团队沉淀下来的规范
数据库·代码规范·设计