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.rhkb.cn/news/37641.html

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

相关文章

【前四届会议均已完成独立出版及EI检索 | 河南大学、河南省科学院主办,多高校单位承协办】第五届信号图像处理与通信国际学术会议(ICSIPC 2025)

第五届信号图像处理与通信国际学术会议&#xff08;ICSIPC 2025&#xff09; 2025 5th International Conference on Signal Image Processing and Communication&#xff08;ICSIPC 2025&#xff09; 会议官网&#xff1a;http://www.icsipc.org 【论文投稿】 会议时间&…

AI 时代的通信新范式:MCP(模块化通信协议)的优势与应用

文章目录 引言 1. 传统 API 的局限性2. MCP&#xff08;模块化通信协议&#xff09;的核心优势2.1 更好的模块化支持2.2 低耦合性与灵活性2.3 高性能数据传输2.4 适配分布式 AI 计算架构 3. AI 时代的 MCP 应用案例4. 结论&#xff1a;AI 时代的通信新范式 引言 在 AI 驱动的现…

Linux 文件系统的日志模式与性能影响

在 Linux 文件系统中&#xff0c;**日志模式&#xff08;Journaling Mode&#xff09;** 是文件系统保证数据一致性和快速恢复的核心机制&#xff0c;但不同的日志模式会对性能产生显著影响。以下是详细分析及优化建议&#xff1a; --- ### **一、日志模式的核心分类** Linux…

TISAX认证注意事项的详细介绍

TISAX&#xff08;Trusted Information Security Assessment Exchange&#xff09;认证的注意事项犹如企业在信息安全领域航行时必须遵循的灯塔指引&#xff0c;至关重要且不容忽视。以下是对TISAX认证注意事项的详尽阐述&#xff1a; 首先&#xff0c;企业需深入研读并理解TI…

Nodejs 项目打包部署方式

方式一&#xff1a;PM2 一、准备工作 确保服务器上已安装 Node.js 环境建议使用 PM2 进行进程管理&#xff08;需要额外安装&#xff09; 二、部署步骤 1.首先在服务器上安装 PM2&#xff08;推荐&#xff09;&#xff1a; npm install -g pm22.将项目代码上传到服务器&…

springboot整合modbus实现通讯

springboot整合modbus4j实现tcp通讯 前言 本文基于springboot和modbus4j进行简单封装&#xff0c;达到开箱即用的目的&#xff0c;目前本方案仅实现了tcp通讯。代码会放在最后&#xff0c;按照使用方法操作后就可以直接使用 介绍 在使用本方案之前&#xff0c;有必要对modb…

【论文阅读】Contrastive Clustering Learning for Multi-Behavior Recommendation

论文地址&#xff1a;Contrastive Clustering Learning for Multi-Behavior Recommendation | ACM Transactions on Information Systems 摘要 近年来&#xff0c;多行为推荐模型取得了显著成功。然而&#xff0c;许多模型未充分考虑不同行为之间的共性与差异性&#xff0c;以…

C/C++蓝桥杯算法真题打卡(Day6)

一、P8615 [蓝桥杯 2014 国 C] 拼接平方数 - 洛谷 方法一&#xff1a;算法代码&#xff08;字符串分割法&#xff09; #include<bits/stdc.h> // 包含标准库中的所有头文件&#xff0c;方便编程 using namespace std; // 使用标准命名空间&#xff0c;避免每次调用…

纯vue手写流程组件

前言 网上有很多的vue的流程组件&#xff0c;但是本人不喜欢很多冗余的代码&#xff0c;喜欢动手敲代码&#xff1b;刚开始写的时候&#xff0c;确实没法下笔&#xff0c;最后一层一层剥离&#xff0c;总算实现了&#xff1b;大家可以参考我写的代码&#xff0c;可以拿过去定制…

[特殊字符][特殊字符][特殊字符][特殊字符][特殊字符][特殊字符]壁紙 流光染墨,碎影入梦

#Cosplay #&#x1f9da;‍♀️Bangni邦尼&#x1f430;. #&#x1f4f7; 穹妹 Set.01 #后期圈小程序 琼枝低垂&#xff0c;霜花浸透夜色&#xff0c;风起时&#xff0c;微光轻拂檐角&#xff0c;洒落一地星辉。远山隐于烟岚&#xff0c;唯余一抹青黛&#xff0c;勾勒出天光水…

kafka压缩

最近有幸公司参与kafka消息压缩&#xff0c;背景是日志消息量比较大。kafka版本2.4.1 一、确认压缩算法 根据场景不同选择不同。如果是带宽敏感患者推荐高压缩比的zstd&#xff0c;如果是cpu敏感患者推荐lz4 lz4和zstd底层都使用的是lz77算法&#xff0c;具体实现逻辑不同&am…

Java EE(14)——网络原理——UDPTCP数据报的结构

前言 本文主要介绍传输层的两个知名协议——UDP&TCP&#xff08;想了解其他层协议请移步Java EE(12)——初始网络&#xff09; 一.传输层的作用 传输层主要实现端对端的数据传输&#xff0c;在传输层的数据报中会包含源端口/目的端口的信息。端口的作用就是标识主机中的…

ccfcsp2701如此编码

//如此编码 #include<iostream> using namespace std; int main(){int n,m;cin>>n>>m;int a[21],b[21],c[21];for(int i1;i<n;i){cin>>a[i];}c[0]1;for(int i1;i<n;i){c[i]c[i-1]*a[i];}b[1](m%c[1])/c[0];int s1,s20;for(int i2;i<n;i){s2s2…

麒麟操作系统安装人大金仓数据库

如果你想拥有你从未拥有过的东西&#xff0c;那么你必须去做你从未做过的事情 在当前数字化转型和信息安全备受重视的背景下&#xff0c;众多公司积极推进国产化改造进程。在操作系统领域&#xff0c;统信、open 欧拉、中标麒麟、银河麒麟等国产操作系统崭露头角&#xff0c;逐…

【工具变量】全国地级市地方ZF债务数据集(2014-2023年)

地方ZF债务是地方财政运作的重要组成部分&#xff0c;主要用于基础设施建设、公共服务及经济发展&#xff0c;是衡量地方财政健康状况的重要指标。近年来&#xff0c;我国地级市的地方ZF债务规模不断变化&#xff0c;涉及一般债务和专项债务等多个方面&#xff0c;对金融市场、…

vlan实验

一、实验拓扑及要求&#xff1a; 二、实验步骤-思路&#xff1a; 实验需求解读&#xff1a; 首先PC1和PC3所在接口为access接口&#xff0c;属于VLAN 2&#xff0c;那么首先需求在SW1和SW2创建VLAN2&#xff0c;并且配置对应连接PC的接口链路类型为Access并放通VLAN 2PC2/4/5…

[samba配置]宿主机访问虚拟机目录

[samba配置]宿主机访问虚拟机目录 1、安装和启动Samba服务 sudo apt update sudo apt install samba2、查看samba服务是否正在运行 sudo systemctl status smbd sudo systemctl status nmbd3、配置samba服务设置为开机启动。 sudo systemctl enable smbd nmbd4、创建一个共…

PDF文件转Markdown,基于开源项目marker

​ 首先我们来问下deepseek 为啥要选marker呢 基于深度学习&#xff0c;一看就逼格拉满。搞科研必备&#xff0c;效果应该不会太差。跟其他的阿猫阿狗工具没法比。 看下官网 https://github.com/VikParuchuri/marker ​ 一看头像是个印度佬&#xff0c;自吹——又快又好。…

【深度学习与大模型基础】第6章-对角矩阵,对称矩阵,正交矩阵

一、对角矩阵 对角矩阵&#xff08;Diagonal Matrix&#xff09;是一种特殊的方阵&#xff0c;其非对角线上的元素均为零&#xff0c;只有对角线上的元素可能非零。具体来说&#xff0c;对于一个 nn的矩阵 A[]&#xff0c;如果满足 则 AA 称为对角矩阵。对角矩阵通常表示为&am…

C语言 数据结构【动态顺序表】详解

引言 详细介绍了顺序表中各个接口的实现&#xff0c;一定要亲自动手敲一遍&#xff0c;要能想象出具体的图像 第一次敲可能不能完全靠自己敲出来&#xff08;很正常&#xff09;&#xff0c;过一段时间可以根据顺序表的原理敲第二遍 孰能生巧 一、线性表 在介绍顺序表之前先…