C语言高频面试题——指针数组和数组指针
指针数组和数组指针是 C/C++ 中容易混淆的两个概念,以下是详细对比:
1. 指针数组(Array of Pointers)
- 定义:一个数组,其元素是 指针类型。
- 语法:
type* arr[元素个数];- 例如:
int* ptr_array[5];表示一个包含 5 个int*类型指针的数组。
- 例如:
- 内存布局:
- 数组本身占用连续内存空间,每个元素存储的是 指针的值(即地址)。
- 每个指针可以指向任意地址(例如不同变量、不同数组的元素)。
- 用途:
- 存储多个指针(如字符串数组、函数指针数组)。
- 示例:
int a = 1, b = 2, c = 3; int* ptr_array[3] = {&a, &b, &c}; // 每个元素指向一个整型变量
2. 数组指针(Pointer to Array)
- 定义:一个指针,指向 数组类型。
- 语法:
type (*ptr)[数组长度];- 例如:
int (*arr_ptr)[10];表示一个指向int[10]类型数组的指针。
- 例如:
- 内存布局:
- 指针本身只存储一个地址(指向数组的首元素)。
- 通过该指针访问时,编译器会根据数组长度计算元素偏移。
- 用途:
- 操作多维数组(如作为函数参数传递二维数组)。
- 示例:
int arr[5] = {1, 2, 3, 4, 5}; int (*arr_ptr)[5] = &arr; // 指向整个数组
关键区别总结
| 特性 | 指针数组 | 数组指针 |
|---|---|---|
| 类型 | 数组元素是 type*(指针) | 指向 type[长度](数组类型) |
| 声明语法 | type* arr[大小]; | type (*ptr)[大小]; |
| 内存占用 | 大小 × sizeof(指针) | sizeof(指针)(通常 8 字节) |
| 解引用操作 | arr[i] 是一个 type* 类型指针 | *ptr 是一个 type[大小] 类型数组 |
| 典型用途 | 存储多个指针(如字符串数组) | 操作多维数组或动态数组 |
示例对比
-
指针数组:
int a = 1, b = 2, c = 3; int* ptr_array[3] = {&a, &b, &c}; printf("%d", *ptr_array[0]); // 输出 1 -
数组指针:
int arr[3] = {10, 20, 30}; int (*arr_ptr)[3] = &arr; printf("%d", (*arr_ptr)[1]); // 输出 20
常见误区
- 语法陷阱:
int* ptr1[5](指针数组)和int (*ptr2)[5](数组指针)的括号位置不同,含义完全不同。 - 数组名 vs 指针:数组名
arr是数组首元素的地址(类型为int*),而&arr是整个数组的地址(类型为int(*)[N])。
总结
- 指针数组:存指针的数组,每个元素是独立指针。
- 数组指针:指向整个数组的指针,通过它访问数组元素时需考虑数组长度。
代码
int arr[3] = {10, 20, 30};
int (*ptr)[3] = &arr; // ptr 是指向数组的指针,类型为 int(*)[3]
表达式 1:*((*ptr) + 1)
分步解析:
ptr的类型:int(*)[3](指向长度为3的数组的指针)。*ptr的类型:int[3](即数组arr本身)。*ptr的退化:在表达式中,数组名会退化为指向首元素的指针,因此*ptr退化为int*类型,指向arr[0]。(*ptr) + 1:*ptr是int*类型,指向arr[0]。+1操作会移动1 * sizeof(int)字节(假设int占4字节)。- 结果地址:
&arr[0] + 1→&arr[1]。
*((*ptr) + 1):- 解引用
&arr[1],得到arr[1]的值 20。
- 解引用
内存布局图示:
arr 地址:0x1000
| 0x1000 | 0x1004 | 0x1008 |
| 10 | 20 | 30 |ptr 地址:0x2000
| 0x2000 |
| 0x1000 | // ptr 存储的是数组 arr 的地址(*ptr) + 1 → 0x1000 + 1 * 4 = 0x1004 → 指向 20
表达式 2:*(ptr + 1)
分步解析:
ptr的类型:int(*)[3](指向长度为3的数组的指针)。ptr + 1:ptr的类型是int(*)[3],因此+1操作会移动1 * sizeof(int[3])字节。sizeof(int[3]) = 3 * 4 = 12字节(假设int占4字节)。- 结果地址:
0x1000 + 12 = 0x100C(超出原数组范围)。
*(ptr + 1):- 解引用非法地址
0x100C,导致 未定义行为(可能读取垃圾值或程序崩溃)。
- 解引用非法地址
内存布局图示:
ptr + 1 → 0x1000 + 12 = 0x100C(该地址未分配给 arr)
| 0x100C | 0x1010 | 0x1014 | ...(未知内存)
| ???? | ???? | ???? |
关键区别总结
| 表达式 | 类型 | 指针运算步长 | 访问的内存地址 | 结果 |
|---|---|---|---|---|
*((*ptr) + 1) | int | 1 * sizeof(int) | &arr[1](合法地址) | 20 |
*(ptr + 1) | int[3](数组) | 1 * sizeof(int[3]) | &arr + 1(非法地址) | 未定义行为(如崩溃) |
为什么会有这样的差异?
ptr的类型决定了指针运算的步长:ptr是int(*)[3],ptr + 1跳过整个数组(3个int)。*ptr退化为int*,(*ptr) + 1跳过一个int。
- 数组指针 vs 普通指针:
ptr是数组指针,操作的是整个数组。*ptr是普通指针,操作的是数组的元素。
类比解释
假设有一个书架:
ptr:指向整个书架(书架地址)。ptr + 1→ 移动到下一个书架(可能不存在)。
*ptr:指向书架上的第一本书(书的地址)。(*ptr) + 1→ 移动到书架上的第二本书。
代码验证
#include <stdio.h>int main() {int arr[3] = {10, 20, 30};int (*ptr)[3] = &arr;printf("表达式1: %d\n", *((*ptr) + 1)); // 输出 20printf("表达式2: %d\n", *(ptr + 1)); // 未定义行为(可能输出垃圾值或崩溃)return 0;
}

总结
*((*ptr) + 1):操作数组元素,合法且安全。*(ptr + 1):操作数组外的内存,危险且非法。
相关文章:
C语言高频面试题——指针数组和数组指针
指针数组和数组指针是 C/C 中容易混淆的两个概念,以下是详细对比: 1. 指针数组(Array of Pointers) 定义:一个数组,其元素是 指针类型。语法:type* arr[元素个数]; 例如:int* ptr_a…...
Linux服务器配置Anaconda环境、Pytorch库(图文并茂的教程)
引言:为了方便后续新进组的 师弟/师妹 使用课题组的服务器,特此编文(ps:我导从教至今四年,还未招师妹) ✅ NLP 研 2 选手的学习笔记 笔者简介:Wang Linyong,NPU,2023级&a…...
Android端使用无障碍服务实现远程、自动刷短视频
最近在做一个基于无障碍自动刷短视频的APP,需要支持用任意蓝牙遥控器远程控制, 把无障碍服务流程大致研究了一下,从下面3个部分做一下小结。 1、需要可调整自动上滑距离和速度以适配不同的屏幕和应用 智能适配99%机型,滑动参数可…...
搭建用友U9Cloud ERP及UAP IDE环境
应用环境 Microsoft Windows 10.0.19045.5487 x64 专业工作站版 22H2Internet Information Services - 10.0.19041.4522Microsoft SQL Server 2019 - 15.0.2130.3 (X64)Microsoft SQL Server Reporing Services 2019 - 15.0.9218.715SQL Server Management Studio -18.6 laster…...
多模态大语言模型arxiv论文略读(二十九)
Temporal Insight Enhancement: Mitigating Temporal Hallucination in Multimodal Large Language Models ➡️ 论文标题:Temporal Insight Enhancement: Mitigating Temporal Hallucination in Multimodal Large Language Models ➡️ 论文作者:Li Su…...
Java开发中的设计模式之观察者模式详细讲解
观察者模式(Observer Pattern)是一种行为型设计模式,它定义了对象之间的一种一对多的依赖关系。当一个对象的状态发生改变时,所有依赖于它的对象都会自动收到通知并更新。这种模式在Java开发中非常常见,尤其是在事件驱…...
基于SpringAI Alibaba实现RAG架构的深度解析与实践指南
一、RAG技术概述 1.1 什么是RAG技术 RAG(Retrieval-Augmented Generation)检索增强生成是一种将信息检索技术与生成式AI相结合的创新架构。它通过以下方式实现智能化内容生成: 知识检索阶段:从结构化/非结构化数据源中检索相关…...
卷积神经网络(CNN)详解
文章目录 引言1.卷积神经网络(CNN)的诞生背景2.卷积神经网络(CNN)介绍2.1 什么是卷积神经网络?2.2 卷积神经网络(CNN)的基本特征2.2.1 局部感知(Local Connectivity)2.2.…...
element-plus添加暗黑模式
main.ts文件 //引入暗黑模式样式 import "element-plus/theme-chalk/dark/css-vars.css"; style.scss文件 // 设置默认主题色 :root {--base-menu-min-width: 80px;--el-color-primary-light-5: green !important;--route--view--background-color: #fff !import…...
【SF顺丰】顺丰开放平台API对接(注册、API测试篇)
1.注册开发者账号 注册地址:顺丰企业账户中心 2.登录开发平台 登录地址:顺丰开放平台 3.开发者对接 点击开发者对接 4.创建开发对接应用 开发者应用中“新建应用”创建应用,最多创建应用限制数量5个 注意:需要先复制保存生产校验…...
VisualSVN过期后的解决方法
作为一款不错的源代码管理软件,svn还是有很多公司使用的。在vs中使用svn,大家一般用的都是VisualSVN插件。在30天试用期过后,它就不能被免费使用了。下面给大家讲如何免费延长过期时间(自定义天数,可以设定一个很大的值…...
代码随想录算法训练营第二十一天
LeetCode题目: 93. 复原 IP 地址78. 子集90. 子集 II2364. 统计坏数对的数目 其他: 今日总结 往期打卡 93. 复原 IP 地址 跳转: 93. 复原 IP 地址 学习: 代码随想录公开讲解 问题: 有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能…...
21. git apply
基本概述 git apply 的作用是:应用补丁文件 基本用法 1.命令格式 git apply [选项] <补丁文件>2.应用补丁 git apply patchfile.patch将补丁应用到工作目录,但不会自动添加到暂存区(需手动 git add) 常用选项 1.检查…...
DeepSeek智能时空数据分析(二):3秒对话式搞定“等时圈”绘制
序言:时空数据分析很有用,但是GIS/时空数据库技术门槛太高 时空数据分析在优化业务运营中至关重要,然而,三大挑战仍制约其发展:技术门槛高,需融合GIS理论、SQL开发与时空数据库等多领域知识;空…...
STM32学习2
一、OLED 1.1 OLED介绍 OLED(Organic Light Emitting Diode):有机发光二极管 OLED显示屏:性能优异的新型显示屏,具有功耗低、相应速度快、宽视角、轻薄柔韧等特点 0.96寸OLED模块:小巧玲珑、占用接口少…...
数据处理: 亲和聚类
Affinity Propagation(亲和传播)是一种基于"消息传递"概念的聚类算法,由Brendan Frey和Delbert Dueck于2007年提出。与K-Means等需要预先指定簇数量的算法不同,Affinity Propagation能够自动确定最佳簇的数量࿰…...
LabVIEW液压系统远程监控与故障诊断
开发了一种基于LabVIEW的远程液压系统监控解决方案,通过先进的数据采集与分析技术,有效提升工程机械的运作效率和故障响应速度。该系统结合现场硬件设备和远程监控软件,实现了液压系统状态的实时检测和故障诊断,极大地提升了维护效…...
Idea中实用设置和插件
目录 一、Idea使用插件 1.Fitten Code智能提示 2.MyBatisCodeHelperPro 3.HighlightBracketPair 4.Rainbow Brackets Lite 5.GitToolBox(存在付费) 6.MavenHelperPro 7.Search In Repository 8.VisualGC(存在付费) 9.vo2dto 10.Key Promoter X 11.CodeGlance…...
安卓处理登录权限问题
在安卓应用中实现登录权限控制,需确保用户登录后才能访问特定功能。以下是分步骤的解决方案: 1. 保存和检查登录状态 使用安全存储保存登录凭证: 推荐使用 EncryptedSharedPreferences 存储敏感信息(如Token、用户ID)…...
Java写数据结构:栈
1.概念: 一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。 压栈:栈的插…...
使用Unity Cache Server提高效率
2021年1月20日19:04:28 1 简介 Unity Cache Server,翻译过来就是Unity缓存服务器 1.1 缓存服务器の官方介绍 Unity 有一个完全自动的资源管线。每当修改 .psd 或 .fbx 文件等源资源时,Unity 都会检测到更改并自动将其重新导入。随后,Unity 以内部格式存储从文件导入的数…...
29个常见的Terraform 面试问题
问题 1:假设您使用 Terraform 创建了一个 EC2 实例,创建完成后,您从状态文件中删除了该条目,那么运行 Terraform Apply 命令时会发生什么? 由于我们已从该状态文件中删除了该条目,因此 Terraform 将不再管…...
机器学习-08-推荐算法-案例
总结 本系列是机器学习课程的系列课程,主要介绍机器学习中关联规则 参考 机器学习(三):Apriori算法(算法精讲) Apriori 算法 理论 重点 MovieLens:一个常用的电影推荐系统领域的数据集 23张图&#x…...
LLM中的N-Gram、TF-IDF和Word embedding
文章目录 1. N-Gram和TF-IDF:通俗易懂的解析1.1 N-Gram:让AI学会"猜词"的技术1.1.1 基本概念1.1.2 工作原理1.1.3 常见类型1.1.4 应用场景1.1.5 优缺点 1.2 TF-IDF:衡量词语重要性的尺子1.2.1 基本概念1.2.2 计算公式1.2.3 为什么需…...
uniapp APP端 DOM生成图片保存到相册
<template> <view class"container" style"padding-bottom: 30rpx;"> <view class"hdbg pr w100 " style"height: 150rpx;"> <top-bar content分享 Back"Back"></top-b…...
Office文件内容提取 | 获取Word文件内容 |Javascript提取PDF文字内容 |PPT文档文字内容提取
关于Office系列文件文字内容的提取 本文主要通过接口的方式获取Office文件和PDF、OFD文件的文字内容。适用于需要获取Word、OFD、PDF、PPT等文件内容的提取实现。例如在线文字统计以及论文文字内容的提取。 一、提取Word及WPS文档的文字内容。 支持以下文件格式: …...
算法——背包问题(分类)
背包问题(Knapsack Problem)是一类经典的组合优化问题,广泛应用于资源分配、投资决策、货物装载等领域。根据约束条件和问题设定的不同,背包问题主要分为以下几种类型: 1. 0-1 背包问题(0-1 Knapsack Probl…...
HXBC编译相关错误
0、Keil MDK报错:Browse information of one or more files is not available----解决方法: 1、使用cubemax生成的工程中,某些引脚自定义了的,是在main.h中,要记得移植。 注意:cubemax生成的spi.c后,在移植的时候,注意hal_driver下面要对应增加hal_stm32H7xxxspi.c …...
Windows 环境下 Apache 配置 WebSocket 支持
目录 前言1. 基本知识2. 实战前言 🤟 找工作,来万码优才:👉 #小程序://万码优才/r6rqmzDaXpYkJZF 爬虫神器,无代码爬取,就来:bright.cn 原先写过apache的http配置:Apache httpd-vhosts.conf 配置详解(附Demo) 1. 基本知识 🔁 WebSocket 是 HTTP 的升级协议 客户…...
运维概述(linux 系统)
1、运维的基本概念 2、企业的运行模式 3、计算机硬件 运维概述 运维岗位的定义 在技术人员(写代码的)之间,一致对运维有一个开玩笑的认知:运维就是修电脑的、装网线的、背锅的岗位。 IT运维管理是指为了保障企业IT系统及网络…...
