当前位置: 首页 > news >正文

【C语言】知识总结·指针篇

前言:

文接上章,在上章节中讲解一些基础函数,循环结构,以及数组,函数的调用。

指针

在 C 语言中,指针是一种极为重要的变量类型,它能够存储内存地址。借助指针,你可以直接对内存进行操作,实现如动态内存分配、传递引用参数等功能。下面将详细讲解 C 语言指针的相关知识。

一·概念

指针是一种变量,其存储的数值是内存地址,通过地址可以改变该地址上的数据


 

二·指针的声明 

数据类型 *指针变量名;
  • 数据类型:表明该指针所指向变量的数据类型。
  • *:用于声明这是一个指针变量。

int *p; // 声明一个指向整型的指针

float *q; // 声明一个指向浮点型的指针

char *str; // 声明一个指向字符型的指针 


 

三·指针的基本操作

1. 取地址运算符(&

&运算符能够获取变量的内存地址。

int num = 42;
int *p = #  // 将num的地址赋值给指针p

2. 解引用运算符(*

*运算符可以访问指针所指向内存地址中的值。

int num = 42;
int *p = #printf("num的值:%d\n", num);      // 输出:42
printf("p指向的值:%d\n", *p);     // 输出:42(通过指针访问)
printf("p存储的地址:%p\n", (void*)p);  // 输出:num的内存地址

3.修改指针指向的值

int num = 42;
int *p = #*p = 100;  // 修改指针所指向的值printf("num的值:%d\n", num);  // 输出:100

四·指针与数组

在 C 语言里,数组名本质上就是数组首元素的地址,这使得指针和数组之间的关系十分紧密。

1.数组名作为指针 

int arr[5] = {1, 2, 3, 4, 5};
int *p = arr;  // 等价于 int *p = &arr[0];printf("arr[0] = %d\n", *p);       // 输出:1
printf("arr[1] = %d\n", *(p + 1));  // 输出:2(指针偏移)

2.指针算术运算

  • 指针加法(p + n:指针向后偏移n个元素的位置(偏移量为n * sizeof(数据类型))。
  • 指针减法(p - n:指针向前偏移n个元素的位置。
  • 指针自增 / 自减(p++p--:指针向后 / 向前偏移 1 个元素的位置。

例如

int arr[5] = {10, 20, 30, 40, 50};
int *p = arr;printf("%d\n", *p);    // 输出:10
printf("%d\n", *(p+2));  // 输出:30(偏移2个元素)

 

 


五·指针作为函数参数

通过指针作为函数参数,可以实现对原始数据的修改(传址调用),还能避免数据的复制,提高效率。

 1. 传址调用示例:交换两个整数的值

#include <stdio.h>void swap(int *a, int *b) {int temp = *a;*a = *b;*b = temp;
}int main() {int x = 5, y = 10;swap(&x, &y);  // 传递变量地址printf("x = %d, y = %d\n", x, y);  // 输出:x = 10, y = 5return 0;
}

2. 数组作为函数参数

数组作为函数参数传递时,会自动转换为指针。

void printArray(int *arr, int size) {for (int i = 0; i < size; i++) {printf("%d ", arr[i]);  // 等价于 *(arr + i)}
}// 调用示例
int arr[5] = {1, 2, 3, 4, 5};
printArray(arr, 5);  // 输出:1 2 3 4 5

 六·指针与字符串

在 C 语言中,字符串通常用字符数组或字符指针来表示。

1. 字符串字面量与字符指针

char *str = "Hello";  // 字符串字面量存储在常量区
printf("%s\n", str);  // 输出:Hello

2. 字符数组与字符指针的区别

// 字符数组(可修改内容)char str1[] = "Hello";
str1[0] = 'J';  // 合法:修改数组元素// 字符指针(指向常量字符串,不可修改)char *str2 = "Hello";
// str2[0] = 'J';  // 非法:修改常量字符串会导致运行时错误

 字符数组可修改,字符指针不可修改。

int  main()
{
    char str[] = "hello world";
    str[0] = 'w';
    printf("%s", str);
    return 0;
} 


七·指针数组与数组指针

1. 指针数组

指针数组是由多个指针组成的数组,其每个元素都是一个指针

 

int a = 10, b = 20, c = 30;
int *arr[3] = {&a, &b, &c};  // 指针数组printf("%d\n", *arr[2]);  // 输出:10

 

2. 数组指针(指向数组的指针)

数组指针是指向整个数组的指针。

int arr[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &arr;  // 数组指针printf("%d\n", (*p)[0]);  // 输出:1

八·函数指针

函数指针是指向函数的指针变量,通过它可以动态调用不同的函数。

#include <stdio.h>int add(int a, int b)
{ return a + b;
}
int sub(int a, int b) 
{ return a - b;
}int main() 
{// 声明函数指针int (*operation)(int, int);// 指向add函数operation = add;printf("5 + 3 = %d\n", operation(5, 3));  // 输出:8// 指向sub函数operation = sub;printf("5 - 3 = %d\n", operation(5, 3));  // 输出:2return 0;
}

 

 2. 函数指针作为参数

void calculate(int a, int b, int (*op)(int, int)) 
{printf("结果:%d\n", op(a, b));
}// 调用示例
calculate(5, 3, add);  // 输出:8
calculate(5, 3, sub);  // 输出:2

九·多级指针

多级指针是指向指针的指针,最常见的是二级指针。

示例:二级指针

int x = 10;
int *p = &x;      // 一级指针
int **pp = &p;    // 二级指针(指向指针的指针)printf("%d\n", **pp);  // 输出:10

十·常见的错误

1·未初始化指针:使用未初始化的指针会导致访问非法内存。

int *p;      // 声明一个整型指针p,但未初始化
*p = 10;     // 错误:对未初始化的指针解引用

正确的是

int num = 0;   // 定义一个整型变量
int *p = &num; // 让p指向num的地址
*p = 10;       // 正确:通过p修改num的值为10
printf("%d", num); // 输出:10

野指针:指针释放后未置为NULL,继续使用会导致问题。

int *p = (int*)malloc(sizeof(int));
free(p);
*p = 10;  // 错误:p已释放

总结

指针是C语言的重中之重,要多加练习,才能掌握。

难点较多,容易错误。

作用:

  • 直接操作内存,提供底层控制能力。
  • 高效传递数据,减少内存开销。
  • 构建复杂数据结构和实现高级编程技巧。

http://www.lryc.cn/news/576066.html

相关文章:

  • linux dts overlay
  • Spearman检验组间相关性及SCI风格绘图
  • 基于社区电商场景的Redis缓存架构实战01-redis内核知识
  • 航拍图像中的“生命线”:基于YOLOv5的7类应急目标检测实践
  • 打造无障碍网页应用的利器:Base UI
  • Python爬虫实战:如何优雅地处理超时和延迟加载问题
  • 安全运营中的漏洞管理和相关KPI
  • 车载以太网-ARP 动态 静态
  • html配置rem实现页面自适应
  • Day57打卡 @浙大疏锦行
  • Go和Elixir极简HTTP服务对比
  • Linux 挂载从入门到精通:mount 命令详解与实战指南
  • 创建一个简单入门SpringBoot3项目
  • Spring Boot项目开发实战销售管理系统——系统设计!
  • Formality:原语(primitive)的概念
  • 中科亿海微SoM模组——基于FPGA+RSIC-V的计算机板卡
  • AI助力游戏设计——从灵感到行动-靠岸篇
  • 《人间词话》PPT课件
  • LeRobot框架设计与架构深度剖析:从入门到精通
  • C#语言入门-task4 :C#语言的高级应用
  • 带标签的 Docker 镜像打包为 tar 文件
  • 七天学会SpringCloud分布式微服务——04——Nacos配置中心
  • Java-异常类
  • Windows Server 2019 查询远程登录源 IP 地址(含 RDP 和网络登录)
  • Spring Boot 性能优化与最佳实践
  • django-celery定时任务
  • Prism框架实战:WPF企业级开发全解
  • Greenplum
  • 鸿蒙OH南向开发 小型系统内核(LiteOS-A)【文件系统】上
  • uni-app uts 插件 android 端 科大讯飞离线语音合成最新版