9.C基础_指针与数组
数组指针(一维数组)
数组指针就是" 数组的指针 ",它是一个指向数组首地址的指针变量。
1、数组名的含义
对于一维数组,数组名就是一个指针,指向数组的首地址。
基于如下代码进行分析:
int a[5] = {1,2,3,4,5};
int* p = a;
- a是数组a[5]的数组名,在这里a是个常量,一定指向的是a[5]的首地址,不能进行" ++ "改值运算。
- p是一个指针变量,它指向了a[5]的首地址,所以它是一个数组指针。在这里p是一个变量,可以进行" ++ "改值运算
2、数组名索引与指针索引
当我们想要访问1这个值的时候,可以有a[0]、*(a+0)、*(p+0)、p[0] 这四种访问形式。
- a[0]:基本的下标法访问
- *(a+0):a可以看作首地址,偏移量为数组的类型int大小,找到地址后解引用也可访问1这个值
- *(p+0):p保存了数组首地址,偏移量为int大小,通过解引用访问地址
- p[0]:特殊,记住即可
注意:*(p+0)、p[0]这两种方法是指针偏移的方法,它实际表示的值与p指向的位置有关。比如p指向的是a[1]这个位置,那么*(p+0)、p[0]访问的不是a[0]而是a[1],而*(p-1)、p[-1]访问的才是a[0]。

3、数组名与数组元素取地址
数组名a与数组元素取地址&a[ i ]它们的值一样,偏移量也一样。但数组名表示整个数组,数组元素取地址仅仅是一个指针。下面分析" a、&a[0]区别 "、" a+1、&a[0]+1 区别"
a、&a[0]的相同点:
- 地址值相同、偏移量也相同。
- 都是常量,都不能进行++等变值操作。
a、&a[0]的不同点:
- a不仅仅指向数组首地址,还可以代表数组;
- &a[0]只是一个指针,什么都不代表。

4、&a是什么
一维数组可以看成列指针,取地址之后变为行指针。
&a的作用与二维数组名类似:a看成列指针,偏移一个数据元素,&a看成行指针偏移一行。

数组指针(二维数组)
1、一维指针遍历二维数组
由于二维数组的元素在内存中是按行序进行排列的,内存排列依旧是连续的。所以在内存方面,它与一维数组没有任何区别,具体的二维数组内存分配如下:

遍历的代码如下:
#include <stdio.h>/* 计算二维数组总大小 */
#define ARRAY2_SIZE(array,type) sizeof(array)/sizeof(type)
/* 计算二维数组中一维数组大小(列大小) */
#define ARRAY2_COL_SIZE(array) sizeof(array[0])
/* 计算二维数组的列数 */
#define ARRAY2_COL_NUM(array,type) ARRAY2_COL_SIZE(array)/sizeof(type)
/* 计算二维数组的行数 */
#define ARRAY2_ROW_NUM(array,type) sizeof(array)/ARRAY2_COL_SIZE(array)int main(){int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};int *p = NULL; int col,row;int i;col = ARRAY2_COL_NUM(a,int);row = ARRAY2_ROW_NUM(a,int);p = &a[0][0];//注意这里的赋值,p赋值的是a[0][0]的地址,而不是直接赋值数组名a for(i=0;i<row*col;i++){printf("%d %d\n",*(p+i),p[i]);} return 0;
}
上述代码有一个注意点,p=&a[0][0]而不是p=a。在二维数组中,尽管&a[0][0]的值与a相同,都是指向数组首地址,但是它们的偏移量不同。
2、二维数组的数组指针
二维数组名是一个指向二维数组的首地址的常量。它是一个代表二维数组,偏移量以行为单位。例如:int a[2][3]它每3列为一行,假设首地址为0x00,那么a+1 = 0x00 + sizeof(int) * 3。
指向二维数组的数组指针被称为" 行指针 "。它的定义形式为:<数据类型>(*变量名)[列数],如上述的int a[2][3],它的数组指针为:int (*p)[3] = a。
3、二维数组元素分析
二维数组可以看成两部分组成:二维数组由多个一维数组组成,一维数组由多个数据组成。
所以二维数组名解引用之后得到的是一维数组名,一维数组名解引用后得到的是数据元素。
即:*a+i = a[i],&a[0] = a
a 与 &a[0] 的区别
相同点:
- 地址值一样,偏移量一样。
- 都是常量,都不能进行++等变值操作。
不同点:
- a不仅仅指向数组首地址,还可以代表数组;
- &a[0]只是一个指针,sizeof(&a[0])返回的是指针大小,而不是二维数组大小
下面是用二维数组的数组指针来遍历的代码:
#include <stdio.h>
/* 计算二维数组总大小 */
#define ARRAY2_SIZE(array,type) sizeof(array)/sizeof(type)
/* 计算二维数组中一维数组大小(列大小) */
#define ARRAY2_COL_SIZE(array) sizeof(array[0])
/* 计算二维数组的列数 */
#define ARRAY2_COL_NUM(array,type) ARRAY2_COL_SIZE(array)/sizeof(type)
/* 计算二维数组的行数 */
#define ARRAY2_ROW_NUM(array,type) sizeof(array)/ARRAY2_COL_SIZE(array)
int main(){int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};int (*p)[4] = a;int row,col;int i,j; row = ARRAY2_ROW_NUM(a,int);col = ARRAY2_COL_NUM(a,int);for(i=0;i<row;i++){for(j=0;j<col;j++){printf("%-2d ",*(*p+j));//p是二维数组指针,*p就是a[i]即一维数组的指针,偏移量为int }printf("\n");p++;//p是二维数组指针,偏移量为sizeof(int)*col即按行偏移 } return 0;
}
上述代码中也可以用一个指针来寻址:例如a[3][4],寻址a[2][1]只需访问&a[0][0]+2*4+1
练习:使用a来访问a[2][1]这个元素
首先需要偏移到第2行,之后偏移到第1列,最后取值
- 偏移到第2行:a+2
- 偏移到第1列之前需要先转换成一维数组名:*(a+2)即a[2]
- 偏移到第1列:*(a+2)+1
- 取值:*(*(a+2)+1)
4、&a是什么
二维数组的&a分析方法与一维数组的分析类似。
- 在一维数组中,我们把a看作列地址,&a看成行地址。
- 在二维数组中,我们把整个二维数组看成列地址,代表偏移量为一行。&a看成行地址,代表偏移量为一整个二维数组。

数组指针(字符串)
字符串是一维数组的一种形式,数组指针的性质与一维数组的数组指针性质完全一样。
下面分析字符串常量与字符串变量的区别:
指针直接赋值字符串,而不是字符数组名时,该指针指向的就是字符串常量。
/* p指向字符串常量,不可修改值 */
char* p = "Hello";/* p指向字符串变量,可以修改值 */
char a[] = "hello";
char*p = a;
相同点:
- 都是存放的字符串的首地址,都可以用%s进行打印
不同点:
- 对于char* p = "Hello";因为它是一个常量,所以不允许修改,即:*p = 'a'是不合法的。
- 对于char* p = a;因为它是一个变量,所以允许修改,即:*p = 'a'是合法的。
相关文章:
9.C基础_指针与数组
数组指针(一维数组) 数组指针就是" 数组的指针 ",它是一个指向数组首地址的指针变量。 1、数组名的含义 对于一维数组,数组名就是一个指针,指向数组的首地址。 基于如下代码进行分析: int a…...
C语言——结构体与共用体
C语言——结构体与共用体 结构体共用体 结构体 如果将复杂的复杂的数据类型组织成一个组合项,在一个组合项中包含若干个类型不同(当然也可以相同)的数据项。 C语言允许用户自己指定这样一种数据结构,它称为结构体。 结构体的语法…...
vs+qt项目转qt creator
1、转换方法 打开vs工程,右键项目,Qt->Create Base .pro File 后面默认OK 如果工程有include和lib路径需要配置,则转换后的工程,需要修改pro文件 2.修改pro文件 例如转换后的工程如下: 修改后 # ------------…...
微信小程序 checkbox 实现双向绑定以及特殊交互处理
wxml文件代码如下: <!--页面顶部 引入wxs文件--> <wxs module"tools" src"../../filter/tools.wxs"></wxs> ... <checkbox-group bindchange"checkboxChange"><label class"weui-cell weui-check__…...
我在高职教STM32——I2C通信之读写EEPROM(1)
大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正是如此,才有了借助CSDN平台寻求认同感和成就感的想法。在这里,我准备陆续把自己花了很多心思设计的教学课件分…...
【ARM】应用ArmDS移植最小FreeRTOS系统
【更多软件使用问题请点击亿道电子官方网站】 一、文档背景 FreeRTOS(Free Real-Time Operating System)是一个开源的实时操作系统内核,广泛应用于嵌入式系统。它具有小巧、灵活、低功耗等特点,支持多任务调度、信号量、队列等实…...
golang下载、上传文件MD5高效计算方法,利用io.TeeReader函数特性 实时计算文件md5签名
在go语言的开发中,当我们在操作下载或者上传文件对象时, 我们可以利用golang内置的io包中的 TeeReader函数特性,高效实时计算文件的md5值。 方法如下: TeeReader高效计算文件md5示例 保存上传文件,并使用文件的md5签…...
TreeMap实现根据值比较
前言: TreeMap普通的排序方法都是根据键来比较来排序,本篇文章实现两种方式实现值排序 1.使用 SortedSet 和 Stream API 如果你想要一个持久化的排序结果,你可以使用 SortedSet 结构来存储键值对的条目。 TreeSet<Map.Entry<String, …...
2024前端面试(内容持续更新)
Vue篇 data为什么是个函数? 在Vue中,data必须是一个函数,这是因为当data是函数时,每个组件实例化时都会调用该函数,返回一个新的数据对象,从而保证每个组件实例拥有独立的数据,避免数据冲…...
接口基础知识5:详解request headers(一篇讲完常见字段)
课程大纲 一、请求头的定义 HTTP请求头部(HTTP Request Headers):HTTP协议中的一部分,用于在客户端和服务器之间传递附加信息。这些头部字段提供了关于请求、客户端环境、或请求的上下文的信息。 请求头是键值对的形式ÿ…...
mac的node使用
查看当前Node和npm版本 node -v npm -v安装"n"版本管理工具 sudo npm install -g n 更新node版本 sudo n stable // 稳定版本 sudo n lts // 最新稳定版本 sudo n latest // 最新版本 sudo n xx.xx // 更新到指定版本查看node版本安装集合 n ls切换对应node版…...
HTML - 简易版打字练习
1. 赛博朋克风格的视觉设计 颜色与渐变:通过linear-gradient设置了背景的颜色渐变,使用高饱和度的霓虹色彩(如橙色、绿色和蓝色)来营造赛博朋克的视觉效果。这种配色方案是赛博朋克风格的典型元素。 立体感和阴影:使用…...
【生成式人工智能-四-chatgpt的训练过程-pretrain预训练自督导式学习督导式学习】
大模型是怎么被训练出来的具有人类智慧的 阶段一训练-自我学习-具备知识训练资料self-supervised learning(自督导式学习) 阶段二-怎么让模型具备人的智慧supervised learning 督导式学习预训练pretrain为什么要用预训练的模型?Adapter逆向工…...
期权价格的奥秘:深入理解影响因素
在金融市场中,期权作为一种衍生工具,为投资者提供了风险管理和资产增值的多种可能性。期权价格的波动往往令人着迷,但其背后的定价机制却充满了复杂性。本文将带您探索期权价格变化的奥秘,并尝试以浅显易懂的方式,解析…...
STM32-USART时序与寄存器状态分析
一、时序分析 在UART(通用异步收发传输)通信中,信号线上的状态分为两种:逻辑1(高电平)和逻辑0(低电平)。在空闲状态下,数据线应保持逻辑高电平。UART协议中的各个信号位具…...
从零安装pytorch并在pycharm中使用
背景介绍 目前主流使用的工具有Facebook搞的pythorch和谷歌开发的tensorflow两种,二者在实现理念上有一定区别,pytorch和人的思维模式与变成习惯更像,而tensorflow则是先构建整体结构,然后整体运行,开发调试过程较为繁…...
开源AI工具FastGPT和RagFlow对比
FastGPT和RagFlow都是基于大型语言模型(LLM)的先进AI系统,它们在多个方面有着各自的特点和优势。 以下是对两者性能的详细对比: 一、系统架构与功能 FastGPT: 数据收集:通过从互联网上收集大量的文本数…...
第N2周:NLP中的数据集构建
对于初学者,NLP中最烦人的问题之一就数据集的构建问题,处理不好就会引起shape问题(各种由于shape错乱导致的问题)。这里给出一个模版,大家可根据这个模版来构建。 torch.utils.data是PyTorch中用于数据加载和预处理的…...
AI助力浮雕创作!万物皆可浮雕?Stable Diffusion AI绘画【浮雕艺术】之文生浮雕!
前言 对于浮雕艺术,其实并不了解。但有幸能和“细辛”前辈结识,对浮雕有了简单的了解,浮雕图案的传统方式是先由画师画出图,然后由雕刻师雕刻。画师画图归为浮雕的设计阶段,画师会绘制出浮雕的设计图,这为…...
你觉得大模型时代该出现什么?
大模型的概念都火了两年了,之前各种媒体吹嘘大模型的出现是类似“蒸汽机时代”、“iPhone时刻”等等。那为什么我们期待的结果都没出现呢?咱们先一起回顾下历史。 1、蒸汽机时代 1.1、蒸汽机历史 许多人都在讨论大模型时代好像只是概念在火࿰…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...
【若依】框架项目部署笔记
参考【SpringBoot】【Vue】项目部署_no main manifest attribute, in springboot-0.0.1-sn-CSDN博客 多一个redis安装 准备工作: 压缩包下载:http://download.redis.io/releases 1. 上传压缩包,并进入压缩包所在目录,解压到目标…...
链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...
