news 2026/5/14 16:01:50

C语言总结10-数组和指针

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言总结10-数组和指针

参考书《C Primer Plus》第六版
10.数组和指针
10.1.1 数组的初始化
数组完全不初始化,其元素的值是随机数。
数组只初始化部分元素,未初始化的元素会被初始化为0。
数组初始化列表元素个数超出数组类型元素个数,有的编译会报错,有的编译器只会警告,忽略初始化列表中多出的元素。
int test1[3];
printf(“test1[0] = %d, test1[1] = %d, test1[2] = %d\n”, test1[0], test1[1], test1[2]); //未初始化就使用,编译器会警告
int a[3] = {0}; //这行代码的意思是把数组的第一个元素a[0]初始化为0,其它未初始化的元素会被编译器自动初始化为0。
int test2[3][2] = {(1,2), (3,4), (5,6)}; //test2[0] = {2, 4}, test2[1] = {6, 0}, test2[2] = {0, 0},编译器会警告
int *pData = test2[0];
printf(“test2[0][0] = %d, test2[0][1] = %d\n”, pData[0], pData[1]); //输出为test2[0][0] = 2, test2[0][1] = 4
pData = test2[1];
printf(“test2[1][0] = %d, test2[1][1] = %d\n”, pData[0], pData[1]); //输出为test2[1][0] = 6, test2[1][1] = 0
pData = test2[2];
printf(“test2[2][0] = %d, test2[2][1] = %d\n”, pData[0], pData[1]); //输出为test2[2][0] = 0, test2[2][1] = 0
int test3[3] = {1, 2, 3, 4, 5};
printf(“test3[0] = %d, test3[1] = %d, test3[2] = %d\n”, test3[0], test3[1], test3[2]);
10.1.2 数组索引
数组索引必须是整数,可以为负数。数组索引为正数表示从前往后数,索引为负数表示从后往前数。
array[-1] = (char *)array + sizeof(array) - 1;
char name[4] = {‘K’, ‘A’, ‘N’, ‘G’};
char *pByte = name + 1;
printf(“BYTE = %c\n”, pByte[-1]); //输出为BYTE = K
pByte = (char *)&name + 1;
printf(“BYTE = %c\n”, pByte[-1]); //输出为BYTE = K
pByte = &name + 1; //编译可通过,但有警告,指针类型不匹配,&name的类型为char (*)[4]
printf(“BYTE = %c\n”, pByte[-1]); //输出为BYTE = G
pByte = (char *)(&name + 1);
printf(“BYTE = %c\n”, pByte[-1]); //输出为BYTE = G
10.6 数组和指针的异同
数组和指针只是访问数据的方式相同,本质上是不同的东西,不能当做同一个东西。
*是数组和指针的解引用操作,[]是数组和指针的索引操作。
(1)数组和指针的共同点:访问数据的方式相同
数组和指针都可以通过解引用形式*(x+i)和索引形式x[i]访问数据。
数组可以通过类似指针的解引用形式*(a+i)访问。
指针可以通过类似数组的索引形式p[i]访问。
(2)数组和指针的差异:本质上是不同的东西
数组首地址所在的存储单元中存储的是数据内容。
指针所在的存储单元中存储的是数据的地址。
数组名不能出现在=左边,即不能向数组名赋值,因为数组首地址是固定的,不能改变。
10.7 指针和多维数组
10.7.2 指针的兼容性
嵌套指针赋值时,把非const指针赋给const指针是不安全的,会导致const失效
int *p;
const int **pp; //const修饰的是紧随其后的int,即(**pp)
pp = &p; //不会报错,但是不安全,会导致const失效
const int n = 8;
*pp = &n; //*pp的值是p,即p = &n,间接把p指向了n
*p = 6; //通过p改变了只读变量n的值,导致pp的const失效了
10.7.3 函数和多维数组
多维数组形参的函数,多维数组形参必须指定最高阶之外的尾数。
当一维数组作为函数参数时,编译器会把数组解析为指向其首元素地址的指针,维数信息会被忽略,但是这条规则并不是递归的。
当多维数组作为函数参数时,编译器只会把数组的最高维解析为指向其首元素地址的指针,低维保持不变。
只有最高维的维数信息会被忽略,低维的维数信息不会被忽略。
只忽略最高维的维数,不影响计算指针的步长,若低维的维数也忽略,指针的步长就无法计算了。
void Func(int p[5])会被解析为 void Func(int *p);
void Func(int *p[5])会被解析为 void Func(int **p);
void Func(int p[4][5])会被解析为void Func(int p[][5])或void Func(int (*p)[5]);
void Func(int p[4][5][6])会被解析为void Func(int p[][5][6])或void Func(int (*p)[5][6])
10.8 函数指针
10.8.1 函数指针的声明和定义
typedef void (*fn_t)(void); 只定义函数指针的类型fn_t,并不定义函数指针变量 fn_t func; 定义函数指针变量func
void (*func)(void); 声明函数指针类型的同时定义函数指针变量func
10.8.2 函数指针的赋值和调用
赋值:func = &test; 或 func = test; 函数名就是函数地址,所以取地址符&可以不加
调用:func(); 或(*func)();
10.8.3 函数指针数组
fn_t func[3]; 或 void (*func[3])(void);
调用方式func[0]();
func[3]是数组,void (*)(void)是函数指针,[]的优先级高于*,所以func优先跟[]结合构成数组
10.8.4 函数指针数组的指针
fn_t (*func)[3];void (*(*func)[3])(void);
调用方式(*func)[2](); 或func[1][2]();
(*func)[3]是数组,func是指向数组的指针。指针func的步长是3个函数指针,func++的结果是func加12个字节。
10.8.5 函数指针作为函数形参
void test(fn_t func);void test(void (*func)(void));
10.8.6 指针和数组运算符的优先级
[]优先级高于*,char*p[5],[]优先与p结合构成数组,数组的元素是char *
.优先级高于**p.data,.优先与data结合构成结构成员取值,结果是*(p.data)
()优先级高于*,char *fn(),fn优先与()构成函数声明,声明的是函数,不是函数指针,所以fn是函数,不是函数指针。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/12 17:54:30

智能家居自动化进阶:基于crazyrouter-skill的跨平台规则引擎实战

1. 项目概述与核心思路最近在折腾智能家居的自动化流程,发现市面上的主流平台虽然功能强大,但总感觉在设备联动和场景自定义上差了那么点意思。要么是支持的设备品牌有限,要么是逻辑编排不够灵活,想实现一个稍微复杂点的“如果A发…

作者头像 李华
网站建设 2026/5/14 7:10:22

基于OpenClaw构建开源项目与Docker镜像自动化监控方案

1. 项目概述 作为一个常年泡在开源社区和容器生态里的开发者,我深知“追新”的痛。今天这个项目发布了v2.0,明天那个镜像更新了安全补丁,手动去GitHub和Docker Hub一个个检查,效率低不说,还容易遗漏关键更新。为了解决…

作者头像 李华
网站建设 2026/5/13 20:13:03

Claude Code用户如何通过Taotoken解决API密钥被封与token不足困扰

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 Claude Code用户如何通过Taotoken解决API密钥被封与token不足困扰 1. 问题背景:开发助手服务的稳定性挑战 许多开发者…

作者头像 李华
网站建设 2026/5/12 17:45:29

告别环境报错!保姆级教程:从JRE到STM32CubeMX 6.10.0的完整安装与配置

从零搭建STM32开发环境:CubeMX 6.10.0避坑全指南 刚拿到STM32开发板时的兴奋,往往在环境配置阶段就被各种报错消磨殆尽。作为过来人,我深刻理解那种看着红色错误提示却无从下手的挫败感。本文将带你用最稳妥的方式完成从Java环境到CubeMX的全…

作者头像 李华