当前位置: 首页 > 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.lqws.cn/news/546247.html

相关文章:

  • 关于SAP产品名称变更通知 SAP云认证实施商工博科技
  • 动态控制click事件绑定
  • H.264中片数据分割(Slice Data Partitioning)介绍
  • Decoder-only PLM GPT1
  • c++异常
  • LINUX625 DNS反向解析
  • gemini-cli 踩坑实录
  • Windows VMWare Centos环境下安装Docker并配置MySql
  • PART 7 视频
  • web布局25
  • iOS打包流程中的安全处理实践:集成IPA混淆保护的自动化方案
  • 消息队列的网络模型详解:IO多路复用、Reactor模型、零拷贝
  • 一键获取服务器硬件脚本:CPU/内存/磁盘/RAID检测脚本详解
  • 电子行业 MES 系统:生产管理的智能引擎
  • Minio的扩容
  • 【docker】docker run参数说明
  • Imbalanced-learn 5. Ensemble of samplers
  • 【水印论文阅读1】将水印规则的定义域从离散的符号空间转移到连续的语义空间
  • 【大模型水印论文阅读2】前缀文本编码、均匀性约束
  • 【linux】程序地址空间
  • 信息抽取领域关键Benchmark方法:分类体系
  • 不同类型的微型导轨精度降低速度有何差异?
  • 专注搜索引擎优化的专业模板平台
  • 【MySQL进阶】服务器配置与管理——系统变量,选项,状态变量
  • CVE-2015-5531源码分析与漏洞复现(Elasticsearch目录遍历漏洞)
  • C语言高级编程
  • 【日志】Unity游戏实习该怎么准备
  • Unity知识点-Renderer常用材质变量
  • 数据结构之顺序表(C语言版本)
  • 【高并发服务器项目测试报告】