C语言-数组指针和指针数组

指针

数组指针与指针数组

数组指针
定义

概念:数组指针是指向数组的指针,本质上还是指针

特点:

①先有数组,后有指针

②它指向的是一个完整的数组

一维数组指针

语法:

 数据类型 (*指针变量名)[容量];

案例:

 /*int arr[] = {11,22,33,44,55};​int *p = arr;p++;*/​​/*************************************************************************> File Name:    demo01.c> Author:       赵生鑫> Description:  > Created Time: 2025年03月20日 星期四 09时48分24秒************************************************************************/​#include <stdio.h>​/***数组指针:指向数组的指针(这里指向整个数组,不是数组的某个元素)** */​int main(int argc,char *argv[]){//一维数组指针//先有数组,再有指针//指针不能独立存在,必须依赖与现有的常量或者变量空间int arr[] = {100,200,300};​//获取数组大小int len = sizeof(arr) / sizeof(arr[0]);​//指针变量指向数组元素:此时指针指向的时数组中的第一个元素,此时指针存储的值是首元素的地址值//数组指针指向整个数组:此时指针指向的是整个数组,此时指针存储的值是首元素的地址值​//定义一个数组指针int (*p)[3] = &arr;//arr默认指向首元素,&arr指向整个数组​//p++  此时不能p++,否则会越界printf("%p,%p,%p\n",p,&arr,arr);//输出3个地址相等​//如何访问数组指针printf("%d\n",(*p)[2]);​//遍历数组指针for ( int i = 0;i < len ;i++){printf("%-6d",(*p)[i]);//数组指针本质是指针,所以我们需要添加()提升指针优先级(默认数组优先)}printf("\n");return 0;}

我们之前所学的是指向数组元素的指针,本质上是指针变量;现在我们学的是指向数组的指针,叫做数组指针

二维数组指针

语法:

 数据类型 (*指针变量名)[行容量][列容量];

案例:

  • 写法1

     /*************************************************************************> File Name:    demo02.c> Author:       赵生鑫> Description:  > Created Time: 2025年03月20日 星期四 10时17分55秒************************************************************************/​#include <stdio.h>​int main(int argc,char *argv[]){int arr[][3] = {11,22,33,44,55,66,77,88,99};​//定义一个数组指针指向二维数组arr//int (*p)[][3] = &arr;   数组指针指向二维数组,不推荐int (*p)[3] = arr;//数组指针指向二维数组首行,推荐​​//遍历(数组方式)for(int i = 0; i < 3;i++){for(int j = 0;j < 3;j++){printf("%-6d",p[i][j]);//arr的地址  等于  p存储的值,也就意味着p等价与arr}printf("\n");}​//p++;//此时是可以使用,因为p指向的是arr中的行,默认为首行return 0;}​
  • 写法2

     /*************************************************************************> File Name:    demo02.c> Author:       赵生鑫> Description:  > Created Time: 2025年03月20日 星期四 10时17分55秒************************************************************************/​#include <stdio.h>​int main(int argc,char *argv[]){int arr[][3] = {11,22,33,44,55,66,77,88,99};​//定义一个数组指针指向二维数组arr//int (*p)[][3] = &arr;   数组指针指向二维数组,不推荐int (*p)[3] = arr;//数组指针指向二维数组首行,推荐​​int rows = sizeof(arr) / sizeof(arr[0]);int cols = sizeof(arr) / sizeof(arr[0]);​for(int i = 0;i < rows;i++){for(int j = 0;j < cols;j++){//三种写法//1.指针数组语法printf("%-6d",p[i][j]);​//2.指针解引用printf("%-6d",*(*(p + i) + j));​//3.混合法printf("%-6d",(*(p + i))[j]);//解引用符*和数组访问符[]在一起时,默认的[]优先级高}printf("\n");}​​//p++;//此时是可以使用,因为p指向的是arr中的行,默认为首行return 0;}​
指针和数组中的符号优先级

() > [] > *

通过指针引用二维数组

注意:二维数组中,数组整体的地址值 = 数组中0行元素的地址值 = 数组中0行0列元素的地址值

案例

案例1

  • 需求:用指向元素的指针变量输出二维数组元素的值

  • 代码:

     /*************************************************************************> File Name:    demo03.c> Author:       赵生鑫> Description:  > Created Time: 2025年03月20日 星期四 11时46分00秒************************************************************************/​#include <stdio.h>​int main(int argc,char *argv[]){//定义一个普通二维数组int arr[3][4] = {10,20,30,40,100,200,300,400,1000,2000,3000,4000};​//定义一个指针变量,用来接收二维数组的元素int *p = arr[0];//0列的位置​//获取元素个数int len = (sizeof(arr) / sizeof(arr[0])) * (sizeof(arr[0]) / sizeof(arr[0][0]));//遍历数组for(;p < arr[0]+len;p++){//每4个换行if((p - arr[0]) % 4 == 0)printf("\n");printf("%-6d",*p);}printf("\n");​​return 0;}​
     ​
指针数组

定义:指针数组是一个数组,数组中的每一个元素都是一个指针

特点:

  • 先有指针,后有数组

  • 指针数组的本质是一个数组,只是数组中的元素类型是指针

语法:

 数据类型 *数组名[容量];
 #include <stdio.h>​int main(){//定义三个变量int a = 10,b = 20,c = 30;//定义指针数组,指针数组是用来存储指针int *arr[3] = {&a,&b,&c};//获取数组大小int len = sizeof(arr) / sizeof(arr[0]);//遍历数组for(int i = 0;i < len; i++){pritnf("%-3d",*arr[i]6);}return 0;}

建议:我们一般使用指针数组处理字符串。

数组指针与指针数组的区别

字符数组和字符指针

字符串实现

再C语言中,表示一个字符串有以下两种方式:

①数组形式:用字符数组存放一个字符串

②指针形式:用字符指针指向一个字符串

案例
 #include <stdio.h>​/*方式1:使用字符数组实现字符串*/void str_test1(){//定义一个伪字符串char str[] = "  I LOVE YOU";printf("%s\n",str);}​​/*方式2:使用字符指针实现字符串*/void str_test2(){//定义一个伪字符串char *str = "I LOVE YOU";printf("%s\n",str);}​​​int main(){str_test1();str_test2();return 0;}

注意:字符数组和字符指针变量都能实现字符串的存储与运算。(字符指针→字符类型的指针变量)

字符数组和字符指针的联系
概念
  • 字符数组由元素组成,每个元素中存放一个字符,而字符指针变量中存放的是地址(可以作为函数参数)

  • 只能对字符数组中的各个元素赋值,而不能用赋值语句对整个字符数组赋值

     char arr[3] = {};arr[2] = 'A';//正确,对字符数组中的元素赋值​arr = {'E','D','F'};//错误,对整个数组赋值(可以理解为数组就是一个常量,一旦创建,就无法改变)
  • 字符数组名虽然代表地址,但数组名的值不能改变,因为数组名是常量(参照上面案例)

  • 对应字符串中的字符的存取,可以用下标法,也可以用指针法。

案例
 #include <stdio.h>​int mian(){//使用两种方式测试字符串char str1[] = "你好,佩奇!";char *str2 = "你好,乔治!";//赋值测试str1 = "你好啊,佩奇!!";//数组一旦创建就无法改变其值,可以理解为数组名是常量str2 = "你好啊,乔治!!";//打印测试printf("%s,%s\n",str1,str2);/*//以下代码会报错//给字符串赋值char *str3 = NULL;//未初始化的指针,指针一定要有指向,需要指向一个具体的内存空间printf("请输入一个符串:\n");scanf("%s",str3);printf("%s\n ",str3);*/char a[] = "I LOVE YOU";char *b = "I LOVE YOU";//使用下标法和指针法分别访问字符串printf("%c,%c\n,%c\n",a[2],*(a+2),b[2],*(b+2))return 0;}
字符串作为形式参数
定义
  • 实参与形参都可以是字符数组

     void fun(char str[],int len){...}void mian(){char str[] = "hello";fun(str,sizeof(str) / sizeof(str[0]))}
  • 实参用字符数组,形参用字符指针

     void fun(char *str,int len){...}void mian(){char *str = "hello";fun(str,sizeof(str) / sizeof(str[0]))}
  • 形参和实现都是指针变量(在函数内部中不对字符串中的字符做修改)

     void fun(char *str,int len){//在函数内部中不对字符串中的字符做修改,否则报段错误//*(str + 2) = 'A';//str[2] = 'A';printf("%s\n",str);}void mian(){char *str = "hello";fun(str,sizeof(str) / sizeof(str[0]))}
  • 实参是指针类型,形参是字符数组(在函数内部中不对字符串中的字符做修改)

     void fun(char str[],int len){//在函数内部中不对字符串中的字符做修改,否则报段错误//*(str + 2) = 'A';//str[2] = 'A';printf("%s\n",str);}void mian(){char *str = "hello";fun(str,sizeof(str) / sizeof(str[0]))}
注意

1.字符数组在创建的时候,会在内存中开辟内存空间,内存空间可以存放字符数据;字符指针在创建的时 候,需要依赖于字符数组,字符指针在内存开辟的内存空间中,存放的是数组元素的地址。字符指针的 创建依赖于字符数组,字符数组可以独立存在,而字符指针不能独立存在。 2.字符数组可以初始化,但是不能赋值;字符指针可以初始化,也可以赋值。

案例
案例1
  • 需求:字符指针作为函数参考:用函数调用实现字符串的复制及长度计算

  • 代码:

     /*************************************************************************> File Name:    demo04.c> Author:       赵生鑫> Description:  > Created Time: 2025年03月20日 星期四 16时55分04秒************************************************************************/​#include <stdio.h>​/***定义一个函数,实现字符串的拷贝,返回字符串的长度*@param source拷贝的源字符串*@param target需要拷贝保存字符串的目标字符串*@return 字符串长度** */int str_copy(const char *source,char *target){//定义一个循环变量register int i = 0;​//循环的遍历while(source[i] != '\0'){//实现拷贝*(target + i) = *(source + i);//指针法​//下标法  target[i] = source[i];​i++;}//拷贝结束后,一定给target加上\0*(target + i) = '\0';​​return i;}​​int main(int argc,char *argv[]){//定义两个数组,从键盘录入字符串char source[20],target[20];​printf("请输入一个字符串:\n");​scanf("%s",source);​//拷贝并复制长度int len = str_copy(source,target);​printf("字符串:%s的长度是%d\n",target,len);​return 0;}​
案例2
  • 需求:字符指针作为函数的参数-给定一个字符串,截取start到end之间的字符串,含头不含尾

  • 代码:

     /*************************************************************************> File Name:    demo05.c> Author:       赵生鑫> Description:  > Created Time: 2025年03月20日 星期四 17时08分51秒************************************************************************/​#include <stdio.h>​/**定义一个函数,实现字符串的截取(含头不含尾)*@param source源字符串*@param start开始截取的位置(下标)*@param end结束截取的位置(下标)*@param target截取出来的字符串*@return target的串长** */int str_substr(const char *source,int start,int end,char *target){//定义循环变量(i时source取的下标,k时target存的下标)register int i = 0,k = 0;​//遍历源字符串while(source[i] != '\0'){//根据start和end截取if(i >= start && i < end){//下标法target[k] = source[i];*(target + k) = *(source + i);k++;}i++;}//target截取结束,需要添加\0*(target + k) = '\0';return k;}​​int main(int argc,char *argv[]){char *str = "abcdefg";char target[26];int len = str_substr(str,2,5,target);printf("%s,%s,%d\n",str,target,len);return 0;}

##

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/74094.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

31天Python入门——第5天:循环那些事儿

你好&#xff0c;我是安然无虞。 文章目录 1. while循环1.1 while循环的嵌套1.2 补充学习:print函数 2. for循环2.1 range函数2.2 for循环2.3 continue和break以及return2.4 for循环的嵌套 3. 补充学习3.1 enumerate函数3.2 zip函数3.3 不要在遍历列表的过程中删除元素 循环 是…

T3 出行:网约车全栈分布式数据库升级实践

现今&#xff0c;网约车已成为民众日常出行不可或缺的选择。伴随“互联网出行”模式的快速推进&#xff0c;庞大的出行数据应运而生&#xff0c;如同构建了城市交通系统的数字神经脉络。与此同时&#xff0c;对高效数据存储与深入数据分析的需求也在持续攀升。 T3 出行于2019年…

区块链技术在供应链管理中的应用与创新

在当今全球化的商业环境中&#xff0c;供应链管理的复杂性与日俱增。从原材料采购到最终产品交付&#xff0c;涉及众多环节和参与者&#xff0c;信息的透明度、准确性和安全性至关重要。区块链技术的出现&#xff0c;为供应链管理带来了全新的解决方案&#xff0c;正在逐步改变…

蓝桥每日打卡--打家劫舍4

#蓝桥#JAVA#打家劫舍4 题目描述 沿街有一排连续的房屋。每间房屋内都藏有一定的现金。现在有一位小偷计划从这些房屋中窃取现金。 由于相邻的房屋装有相互连通的防盗系统&#xff0c;所以小偷 不会窃取相邻的房屋 。 小偷的 窃取能力 定义为他在窃取过程中能从单间房屋中窃…

c#难点整理

1.何为托管代码&#xff0c;何为非托管代码 托管代码就是.net框架下的代码 非托管代码&#xff0c;就是非.net框架下的代码 2.委托的关键知识点 将方法作为参数进行传递 3.多维数组 4.锯齿数组 5.多播委托的使用 6.is运算符 相当于逻辑运算符是 7.as 起到转换的作用 8.可…

Nginx代理本机的443到本机的8080端口

1. 准备工作 确认已生成 IP 的 HTTPS 证书 假设你已通过 mkcert 生成证书&#xff08;如 192.168.199.191.pem 和 192.168.199.191-key.pem&#xff09;&#xff0c;并已安装 CA 证书&#xff08;运行过 mkcert -install&#xff09;。 Nginx 安装 • 若未安装 Nginx&#…

善用批处理的for命令倍增效率(附彩蛋:windows官方bug)

前言 在我们工作中,如果使用Windows系统,善用批处理命令,特别是在批量的文件处理,文本处理时能帮助我们极大地提升工作效率,起到事半功倍的效果! 但很多同学,对批处理的使用更多还停留在可以将多个command命令组合到一起执行,省去重复敲命令和等待的时间。这个其实只…

数据结构之栈的2种实现方式(顺序栈+链栈,附带C语言完整实现源码)

对于逻辑关系为“一对一”的数据&#xff0c;除了用顺序表和链表存储外&#xff0c;还可以用栈结构存储。 栈是一种“特殊”的线性存储结构&#xff0c;它的特殊之处体现在以下两个地方&#xff1a; 1、元素进栈和出栈的操作只能从一端完成&#xff0c;另一端是封闭的&#xf…

Camera2 API拍照失败问题实录:从错误码到格式转换的排坑之旅

一、问题背景 在开发基于Camera2 API的相机应用时&#xff0c;我们遇到了一个棘手的问题&#xff1a;预览功能在所有设备上工作正常&#xff0c;但在某特定安卓设备上点击拍照按钮后无任何响应。值得注意的是&#xff0c;使用旧版Camera API时该设备可以正常拍照。本文记录了完…

Jmeter旧版本如何下载

1.Jmeter最新版本下载位置 https://jmeter.apache.org/download_jmeter.cgi2.Jmeter旧版本下载位置 https://archive.apache.org/dist/jmeter/binaries稳定版本&#xff1a;5.4.1

css-grid布局

文章目录 1、布局2、网格轨道3、间距Gap4、网格线5、网格别名 当一个 HTML 元素将 display 属性设置为 grid 或 inline-grid 后&#xff0c;它就变成了一个网格容器&#xff0c;这个元素的所有直系子元素将成为网格元素。 1、布局 启用grid布局类似与flex布局&#xff0c;不过g…

SolidWorks使用显卡教程

操作步骤&#xff1a; 打开注册表编辑器 按下键盘上的 Win R 组合键&#xff0c;输入 regedit 并按回车键&#xff0c;打开注册表编辑器。 导航到显卡信息路径 在注册表中依次展开以下路径&#xff1a; plaintext HKEY_CURRENT_USER\Software\SolidWorks\SOLIDWORKS 2021\Per…

【C++11】左值引用、右值引用、移动语义和完美转发

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:C ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;左值引用和右值引用 &#x1f38f;左值和左值引用 &#x1f38f;右值和右值引用 &#x1f4cc;左值引用和右值引用比较 &#x1f38f;左值引用 &#x1f38f;右值…

麒麟系列Linux发行版探秘

以下内容摘自《银河麒麟操作系统进阶应用》一书。 银河麒麟操作系统&#xff08;Kylin&#xff09; 银河麒麟&#xff08;Kylin&#xff09;操作系统是中国自主研发的一款基于Linux内核的操作系统。它的发展历程可以追溯到2002年&#xff0c;最初由国防科技大学主导研发&…

【机密计算顶会解读】11:ACAI——使用 Arm 机密计算架构保护加速器执行

导读&#xff1a;本文介绍ACAI&#xff0c;其构建一个基于CCA的解决方案&#xff0c;使得机密虚拟机能够安全地使用加速器&#xff0c;同时保持与现有应用程序的兼容性和安全性&#xff0c;能够实现对加速器的安全访问。 原文链接&#xff1a;ACAI: Protecting Accelerator Ex…

第一天 UnityShader的结构

Shader初学者的学习笔记 第一天 Unity Shader的结构 文章目录 Shader初学者的学习笔记前言一、Unity Shader结构二、Unity Shader结构解析① Properties② Tags③ RenderSetup(可选状态)④ Name⑤ [Tags]⑥ [RenderSetup]⑦ 顶点着色器和片元着色器的代码 (Unity最聪明的孩子)…

VL开源模型实现文本生成图片

一、 基础知识 根据描述生成图片的视觉-语言模型&#xff08;Vision-Language Models, VL 模型&#xff09;是近年来多模态生成领域的热点研究方向。这些模型能够根据自然语言描述生成高质量的图像&#xff0c;广泛应用于艺术创作、设计辅助、虚拟场景构建等领域。 1 根据描述…

【Java SE】抽象类/方法、模板设计模式

目录 1.抽象类/方法 1.1 基本介绍 1.2 语法格式 1.3 使用细节 2. 模板设计模式&#xff08;抽象类使用场景&#xff09; 2.1 基本介绍 2.2 具体例子 1.抽象类/方法 1.1 基本介绍 ① 当父类的某些方法&#xff0c;需要声明&#xff0c;但是又不确定如何实现时&#xff…

【人工智能】LM Studio 的 GPU 加速:释放大模型推理潜能的极致优化

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着大语言模型(LLM)的广泛应用,其推理效率成为限制性能的关键瓶颈。LM Studio 作为一个轻量级机器学习框架,通过 GPU 加速显著提升了大…

深度学习:从零开始的DeepSeek-R1-Distill有监督微调训练实战(SFT)

原文链接&#xff1a;从零开始的DeepSeek微调训练实战&#xff08;SFT&#xff09; 微调参考示例&#xff1a;由unsloth官方提供https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen2.5_(7B)-Alpaca.ipynbhttps://colab.research.google.com/git…