当前位置: 首页 > news >正文

c语言基础-------数组元素的指针

在 C 语言中,数组指针是一个指针变量,它存储了数组首元素的地址。由于数组名通常被视为指向数组首元素的指针,因此数组指针可以用来遍历数组、访问数组元素以及进行数组操作。

数组指针

声明数组指针

声明数组指针的基本语法是在指针类型后加上方括号,并在方括号内指定数组的大小。

int (*ptr)[5]; // 声明一个指向包含 5 个 int 元素的数组的指针

在这个例子中,ptr 是一个指向数组的指针,这个数组包含 5 个 int 类型的元素。

初始化数组指针

数组指针的初始化通常是将一个数组的地址赋值给它。

int arr[5] = {1, 2, 3, 4, 5};
int (*ptr)[5] = arr; // 将 arr 的地址赋值给 ptr

使用数组指针

一旦数组指针被初始化,它就可以用来访问数组中的元素。

for (int i = 0; i < 5; i++) {printf("%d ", (*ptr)[i]); // 输出 arr[i] 的值
}

数组指针与指针数组

数组指针和指针数组是两个不同的概念。

  • 数组指针:指向一个数组的指针,如上面的例子。
  • 指针数组:一个数组,其中每个元素都是一个指针。

注意事项

  • 数组指针必须指向与其类型匹配的数组。
  • 数组指针可以进行算术运算,但是只能在其指向的数组内部进行。
  • 数组指针通常用于数组操作和数组元素访问。
    正确地使用数组指针是 C 语言编程中的一个重要概念,尤其是在处理多维数组和复杂数据结构时。

在这里插入图片描述

代码示例 原理

在 C 语言中,数组指针可以用来简化对数组元素的访问和操作。以下是一个简单的代码示例,展示了如何使用数组指针来遍历一个数组并打印每个元素的值:

#include <stdio.h>
int main() {int arr[5] = {1, 2, 3, 4, 5};int (*ptr)[5]; // 声明一个指向包含 5 个 int 元素的数组的指针// 初始化数组指针ptr = arr; // 将 arr 的地址赋值给 ptr// 使用数组指针遍历数组并打印每个元素的值for (int i = 0; i < 5; i++) {printf("%d ", *(*(ptr + i) + i)); // 输出 arr[i][i] 的值}return 0;
}

在这个示例中,我们首先声明了一个名为 arr 的整型数组,并初始化了它。然后,我们声明了一个名为 ptr 的数组指针,它指向一个包含 5 个整型元素的数组。
接下来,我们初始化 ptrarr 的地址。然后,我们使用一个 for 循环来遍历数组 arr。在循环中,我们使用指针算术来访问每个元素的值,并通过解引用操作来打印它们。
这里的关键点是:

  1. 数组指针声明int (*ptr)[5] 声明了一个指向包含 5 个整型元素的数组的指针。
  2. 数组指针初始化ptr = arr; 将数组 arr 的地址赋值给指针 ptr
  3. 指针算术ptr + i 表示 ptr 指向的数组中的第 i 个元素,而 *(ptr + i) 表示这个元素的值。
  4. 解引用指针*(*(ptr + i) + i) 表示 ptr 指向的数组中的第 i 个元素的第 i 个子元素。在这个例子中,由于 ptr 指向的数组是单维的,所以 *(*(ptr + i) + i) 实际上是 arr[i][i]
    通过这个示例,我们可以看到数组指针如何简化对数组元素的访问和操作。正确地使用数组指针可以提高程序的效率和可读性。

通过指针引用数组元素

在 C 语言中,通过指针引用数组元素是一种常见操作,它允许我们使用指针来间接访问数组中的元素。以下是一个简单的示例,展示了如何通过指针引用数组元素:

#include <stdio.h>
int main() {int arr[5] = {1, 2, 3, 4, 5};int *ptr; // 声明一个整型指针变量// 初始化指针ptr = arr; // 将数组 arr 的地址赋值给指针 ptr// 通过指针引用数组元素printf("Array elements accessed through pointer: ");for (int i = 0; i < 5; i++) {printf("%d ", *(ptr + i)); // 输出数组 arr 的元素}printf("\n");return 0;
}

在这个示例中,我们首先声明了一个名为 arr 的整型数组,并初始化了它。然后,我们声明了一个名为 ptr 的整型指针变量。
接下来,我们初始化 ptrarr 的地址。这意味着 ptr 现在指向 arr 的第一个元素 arr[0]
在 for 循环中,我们使用指针算术 ptr + i 来访问数组 arr 中的每个元素。由于 ptr 指向数组的第一个元素,ptr + i 实际上是 arr[i] 的地址。通过解引用操作 *(ptr + i),我们可以访问数组中的元素值。
通过这个示例,我们可以看到如何通过指针来间接访问数组元素。这种方法在处理大型数组时非常有用,因为它可以减少代码的复杂性,并且更高效。正确地使用指针是 C 语言编程中的一个重要概念,尤其是在进行数组操作时。

下标法和指针法

在 C 语言中,数组元素可以通过下标法或指针法来访问。这两种方法在语法和性能上有所不同,但它们本质上是等效的。

下标法

下标法是 C 语言中访问数组元素的传统方式,它使用数组的索引来直接定位元素。

int arr[5] = {1, 2, 3, 4, 5};
int element = arr[2]; // 访问 arr 数组的第三个元素

下标法的语法简单直观,但有一个缺点:它不适用于指针数组(即数组中存储的是指针)。

指针法

指针法是通过指针来间接访问数组元素。指针法可以用于数组中的任何元素,包括指针数组。

int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // 指针 ptr 指向数组 arr 的第一个元素
int element = *(ptr + 2); // 访问 arr 数组的第三个元素

指针法的关键在于指针的算术运算。指针 ptr 指向数组 arr 的第一个元素,因此 ptr + 2 指向 arr[2]。通过解引用操作 *(ptr + 2),我们可以访问 arr[2] 的值。
指针法的优点是可以更容易地处理指针数组,但它需要更多的理解,尤其是在处理指针算术时。

性能

从性能的角度来看,下标法和指针法在大多数情况下是相同的,因为编译器会优化这两种方法。但是,指针法在处理指针数组时更加灵活和高效。

总结

  • 下标法是通过数组的索引来直接访问元素。
  • 指针法是通过指针来间接访问元素,适用于处理指针数组。
  • 两种方法在性能上通常相同,但在处理指针数组时,指针法更加灵活和高效。
    选择哪种方法取决于具体的需求和上下文。

代码示例:

在 C 语言中,下标法和指针法都可以用来访问数组元素。以下是一个简单的示例,展示了如何使用这两种方法来访问数组元素:

#include <stdio.h>
int main() {int arr[5] = {1, 2, 3, 4, 5};int *ptr; // 声明一个整型指针变量// 下标法访问数组元素printf("Array elements accessed using indexing: ");for (int i = 0; i < 5; i++) {printf("%d ", arr[i]); // 输出数组 arr 的元素}printf("\n");// 指针法访问数组元素printf("Array elements accessed using pointers: ");ptr = arr; // 指针 ptr 指向数组 arr 的第一个元素for (int i = 0; i < 5; i++) {printf("%d ", *(ptr + i)); // 输出数组 arr 的元素}printf("\n");return 0;
}

在这个示例中,我们首先声明了一个名为 arr 的整型数组,并初始化了它。然后,我们声明了一个名为 ptr 的整型指针变量。
接下来,我们使用两个 for 循环来分别使用下标法和指针法来访问数组 arr 的元素。

  1. 下标法arr[i] 直接访问数组 arr 中的第 i 个元素。
  2. 指针法*(ptr + i) 通过指针 ptr 来间接访问数组 arr 中的第 i 个元素。由于 ptr 指向数组的第一个元素,ptr + i 实际上是 arr[i] 的地址,通过解引用操作 *(ptr + i),我们可以访问 arr[i] 的值。
    通过这个示例,我们可以看到下标法和指针法如何用来访问数组元素。正确地使用这两种方法是 C 语言编程中的一个重要概念,尤其是在进行数组操作时。

在这里插入图片描述

通过数组名计算出数组元素的地址,找出数组元素的值

在 C 语言中,数组名通常可以被看作是一个指向数组首元素的指针。因此,我们可以通过数组名来计算出数组元素的地址,并通过解引用指针来获取元素的值。
以下是一个简单的示例,展示了如何通过数组名计算出数组元素的地址,并找出数组元素的值:

#include <stdio.h>
int main() {int arr[5] = {1, 2, 3, 4, 5};int *ptr; // 声明一个整型指针变量// 通过数组名计算数组元素的地址printf("Address of arr[0]: %p\n", arr); // 输出数组 arr 的第一个元素的地址printf("Address of arr[1]: %p\n", arr + 1); // 输出数组 arr 的第二个元素的地址printf("Address of arr[2]: %p\n", arr + 2); // 输出数组 arr 的第三个元素的地址printf("Address of arr[3]: %p\n", arr + 3); // 输出数组 arr 的第四个元素的地址printf("Address of arr[4]: %p\n", arr + 4); // 输出数组 arr 的第五个元素的地址// 通过解引用指针来获取数组元素的值printf("Value of arr[0]: %d\n", *arr); // 输出数组 arr 的第一个元素的值printf("Value of arr[1]: %d\n", *(arr + 1)); // 输出数组 arr 的第二个元素的值printf("Value of arr[2]: %d\n", *(arr + 2)); // 输出数组 arr 的第三个元素的值printf("Value of arr[3]: %d\n", *(arr + 3)); // 输出数组 arr 的第四个元素的值printf("Value of arr[4]: %d\n", *(arr + 4)); // 输出数组 arr 的第五个元素的值return 0;
}

在这个示例中,我们首先声明了一个名为 arr 的整型数组,并初始化了它。然后,我们声明了一个名为 ptr 的整型指针变量。
接下来,我们使用数组名 arr 来计算数组元素的地址。由于 arr 是一个指向数组首元素的指针,我们可以通过算术运算 arr + i 来计算出数组中第 i 个元素的地址,其中 i 是数组元素的索引。
然后,我们通过解引用指针 *(arr + i) 来获取数组中第 i 个元素的值。
通过这个示例,我们可以看到如何通过数组名来计算出数组元素的地址,并通过解引用指针来获取元素的值。正确地使用数组名和指针是 C 语言编程中的一个重要概念,尤其是在进行数组操作时。

用指针变量指向数组元素

在 C 语言中,你可以使用指针变量来指向数组元素。这通常涉及到声明一个指针变量,然后将数组元素的地址赋值给它。以下是一个简单的示例,展示了如何使用指针变量指向数组元素:

#include <stdio.h>
int main() {int arr[5] = {1, 2, 3, 4, 5};int *ptr; // 声明一个整型指针变量// 初始化指针变量,使其指向数组 arr 的第一个元素ptr = arr;// 通过指针变量访问数组元素printf("Array elements accessed through pointer: ");for (int i = 0; i < 5; i++) {printf("%d ", *(ptr + i)); // 输出数组 arr 的元素}printf("\n");return 0;
}

在这个示例中,我们首先声明了一个名为 arr 的整型数组,并初始化了它。然后,我们声明了一个名为 ptr 的整型指针变量。
接下来,我们初始化 ptrarr 的地址。这意味着 ptr 现在指向 arr 的第一个元素 arr[0]
在 for 循环中,我们使用指针算术 ptr + i 来访问数组 arr 中的每个元素。由于 ptr 指向数组的第一个元素,ptr + i 实际上是 arr[i] 的地址。通过解引用操作 *(ptr + i),我们可以访问 arr[i] 的值。
通过这个示例,我们可以看到如何使用指针变量来指向数组元素。这种方法在处理大型数组时非常有用,因为它可以减少代码的复杂性,并且更高效。正确地使用指针是 C 语言编程中的一个重要概念,尤其是在进行数组操作时。

在这里插入图片描述

三种方法的比较

在 C 语言中,数组元素可以通过下标法、指针法和数组指针法来访问。以下是这三种方法的比较:

  1. 下标法
    • 语法:数组名[索引]
    • 示例:arr[i]
    • 优点:简单直观,易于理解。
    • 缺点:不适用于指针数组。
    • 性能:与指针法相似,编译器会优化。
  2. 指针法
    • 语法:*(指针变量 + 索引)*(指针变量 + 索引 * 元素大小)
    • 示例:*(ptr + i)*(ptr + i * sizeof(int))
    • 优点:适用于指针数组,可以更容易地处理指针数组。
    • 缺点:需要更多理解,尤其是在处理指针算术时。
    • 性能:与下标法相似,编译器会优化。
  3. 数组指针法
    • 语法:*(数组指针变量 + 索引)*(数组指针变量 + 索引 * 元素大小)
    • 示例:*(*(ptr + i))*(*(ptr + i * sizeof(int)))
    • 优点:适用于指针数组,可以更容易地处理指针数组。
    • 缺点:需要更多理解,尤其是在处理指针算术时。
    • 性能:与下标法和指针法相似,编译器会优化。
      总结:
  • 下标法和指针法在性能上通常相同,但在处理指针数组时,指针法更加灵活和高效。
  • 数组指针法与指针法在性能上通常相同,但在处理指针数组时,数组指针法更加灵活和高效。
  • 选择哪种方法取决于具体的需求和上下文。
    正确地使用这些方法是 C 语言编程中的一个重要概念,尤其是在进行数组操作时。

在这里插入图片描述

使用指针变量指向数组元素注意事项

在 C 语言中,使用指针变量指向数组元素时,需要注意以下几点:

  1. 指针类型:指针的类型必须与其指向的数据类型匹配。例如,一个 int * 类型的指针只能指向 int 类型的变量。
  2. 指针初始化:在使用指针之前,必须将其初始化为一个有效的地址。未初始化的指针可能导致程序崩溃或不可预测的行为。
  3. 指针算术:指针可以进行算术运算,如增加或减少其值。但是,只有对数组指针进行算术运算才是合法的,对于非数组指针进行算术运算会导致未定义行为。
  4. 数组指针与指针数组:数组指针是指向数组的指针,而指针数组是一个数组,其中每个元素都是一个指针。
  5. 指针与数组名:数组名通常可以被视为指向数组首元素的指针。但是,数组名是一个常量指针,不能被重新赋值。
  6. 指针作为函数参数:当指针作为函数参数传递时,函数内部对指针的修改会影响到原始变量。
  7. 动态内存分配:在使用动态内存分配(如 malloccalloc)时,确保在不再需要时释放内存(使用 free)。
  8. 避免野指针:不要使用未初始化的指针。确保所有指针在使用前都已正确初始化。
  9. 指针与 sizeof 运算符:使用 sizeof 运算符时要注意,对指针使用 sizeof 得到的是指针本身的大小,而不是它所指向的数据的大小。
  10. 数组指针与指针数组:数组指针是指向数组的指针,而指针数组是一个数组,其中每个元素都是一个指针。
    正确地使用指针变量指向数组元素是 C 语言编程中的一个重要概念,尤其是在进行数组操作和内存管理时。遵循这些注意事项可以帮助你编写更安全、更可靠的 C 语言代码。

数组名作为函数参数

在 C 语言中,数组名作为函数参数时,实际上传递的是数组首元素的地址。这意味着,当一个函数接受一个数组名作为参数时,它接收的是数组首元素的地址,而不是整个数组的大小。

示例

#include <stdio.h>
// 函数原型声明
void printArray(int arr[], int size);
int main() {int arr[5] = {1, 2, 3, 4, 5};printArray(arr, 5); // 调用函数并传递数组名和数组长度return 0;
}
// 函数定义
void printArray(int arr[], int size) {for (int i = 0; i < size; i++) {printf("%d ", arr[i]);}printf("\n");
}

在这个示例中,printArray 函数接受一个整型数组 arr[] 和数组的大小 size。在 main 函数中,我们调用 printArray 函数并传递数组名 arr 和数组长度 5

原理

  • 数组名在大多数情况下可以被视为指向数组首元素的指针。
  • 当数组名作为函数参数传递时,实际上传递的是数组首元素的地址。
  • 函数内部可以通过指针算术来访问数组中的元素。
  • 由于数组名是一个常量指针,它不能被重新赋值。
    正确地使用数组名作为函数参数是 C 语言编程中的一个重要概念,尤其是在进行数组操作和函数设计时。遵循这些原则可以帮助你编写更清晰、更高效的 C 语言代码。

在这里插入图片描述

数组名 作为函数参数是指针数组吗

在 C 语言中,数组名作为函数参数并不是指针数组。数组名通常被视为指向数组首元素的指针,而不是指针数组。以下是一些关键点来区分这两者:

  1. 数组名作为函数参数
    • 当数组名作为函数参数传递时,它传递的是数组首元素的地址,而不是数组的大小。
    • 函数内部可以通过指针算术来访问数组中的元素。
    • 数组名是一个常量指针,不能被重新赋值。
  2. 指针数组
    • 指针数组是一个数组,其中每个元素都是一个指针。
    • 指针数组的元素可以指向不同的内存地址。
    • 指针数组可以作为函数参数传递,并且函数内部可以通过指针数组的元素来访问多个不同的数据结构。

示例

#include <stdio.h>
// 函数原型声明
void printArray(int arr[], int size); // 数组名作为函数参数
void printPointerArray(int *ptr[], int size); // 指针数组作为函数参数
int main() {int arr[5] = {1, 2, 3, 4, 5};int *ptr[5] = {&arr[0], &arr[1], &arr[2], &arr[3], &arr[4]}; // 指针数组初始化printArray(arr, 5); // 调用函数并传递数组名和数组长度printPointerArray(ptr, 5); // 调用函数并传递指针数组和数组长度return 0;
}
// 函数定义
void printArray(int arr[], int size) {for (int i = 0; i < size; i++) {printf("%d ", arr[i]);}printf("\n");
}
void printPointerArray(int *ptr[], int size) {for (int i = 0; i < size; i++) {printf("%d ", *ptr[i]);}printf("\n");
}

在这个示例中,printArray 函数接受一个整型数组 arr[] 和数组的大小 size,而 printPointerArray 函数接受一个整型指针数组 ptr[] 和数组的大小 size

总结

  • 数组名作为函数参数是指向数组首元素的指针。
  • 指针数组是一个数组,其中每个元素都是一个指针。
  • 两者在概念和使用上有所不同,正确地理解和使用它们对于编写有效的 C 语言程序至关重要。

在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 2024新型数字政府综合解决方案(七)
  • Apache Doris 中Compaction问题分析和典型案例
  • drawio的问题
  • 24 初入python
  • ECMAScript性能优化技巧与陷阱
  • 【线性代数】几种行/列向量相乘的情况讨论
  • 基于vue全家桶的pc端仿淘宝系统_kebgy基于vue全家桶的pc端仿淘宝系统_kebgy--论文
  • 100个练习学习Rust!可变性・循环・溢出
  • IIS发布打包后文件
  • 【软件测试】如何用python连接Linux服务器
  • 前端宝典之六:React源码解析之lane模型
  • Android MVVM框架详解与应用
  • # 利刃出鞘_Tomcat 核心原理解析(七)
  • CentOS 7 安装流程详细教程
  • 【嵌入式烧录刷写文件】-1.10-为一个Motorola S-record(S19/SREC/mot/SX)文件计算“校验和Checksum”
  • (三)从jvm层面了解线程的启动和停止
  • 【前端学习】-粗谈选择器
  • 2017 年终总结 —— 在路上
  • 2018一半小结一波
  • Angular 响应式表单 基础例子
  • Angularjs之国际化
  • Debian下无root权限使用Python访问Oracle
  • gcc介绍及安装
  • HomeBrew常规使用教程
  • javascript 哈希表
  • JavaScript服务器推送技术之 WebSocket
  • jdbc就是这么简单
  • Swift 中的尾递归和蹦床
  • windows-nginx-https-本地配置
  • 笨办法学C 练习34:动态数组
  • 关于 Linux 进程的 UID、EUID、GID 和 EGID
  • 免费小说阅读小程序
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 小程序button引导用户授权
  • 深度学习之轻量级神经网络在TWS蓝牙音频处理器上的部署
  • elasticsearch-head插件安装
  • gunicorn工作原理
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • zabbix3.2监控linux磁盘IO
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • # Kafka_深入探秘者(2):kafka 生产者
  • #define
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • (2)(2.10) LTM telemetry
  • (2)nginx 安装、启停
  • (52)只出现一次的数字III
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (八)Spring源码解析:Spring MVC
  • (苍穹外卖)day03菜品管理
  • (层次遍历)104. 二叉树的最大深度
  • (附源码)springboot社区居家养老互助服务管理平台 毕业设计 062027
  • (黑客游戏)HackTheGame1.21 过关攻略
  • (精确度,召回率,真阳性,假阳性)ACC、敏感性、特异性等 ROC指标