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

C++自学笔记---数组和指针的异同点

数组和指针的异同点

0. 复习一下:指针运算符 * 和 &

我们前两篇有讲过这两个运算符,& 是取地址运算符,* 是解引用运算符。这两个运算符是理解指针的关键,因为它们分别代表了获取变量地址访问指针指向的值这两个基本操作。那么在理解数组和指针之前,我们先把这两个符号的意义记在心里。

#include <iostream>
using namespace std;

int main() {
    int a = 10;
    int* ptr = &a;

    cout << "变量 a 的值: " << a << endl;
    cout << "变量 a 的地址: " << &a << endl;
    cout << "指针 ptr 存储的地址: " << ptr << endl;
    cout << "*ptr的值:"<< *ptr <<endl;

    return 0;
}

运行结果

  • a 是一个整型变量,值为 10。
  • &a 获取变量 a 的内存地址。
  • ptr 是一个指向整型的指针,它存储了 a 的地址。
  • *ptr解引用 ptr,获取 ptr 指向的内存地址中的值(即 a 的值),为10。

1. 数组和指针的的异同点

数组和指针都与内存地址相关:数组名本质上是一个指向数组首元素的指针。指针也可以指向数组中的某个元素。但是数组名数组名本身是一个常量指针,不能重新赋值为其他地址。指针变量可以重新赋值,指向不同的地址。也就是说,数组名只能指向数组的首元素,指针可以指向数组中的任意元素。
我们可以通过这个例子来理解一下这个特性:

#include <iostream>
using namespace std;

int main() {
    // 定义一个数组
    int arr1[] = {1, 2, 3, 4, 5};
    int arr2[] = {6, 7, 8, 9, 10};

    // 数组名是常量指针,指向数组的首元素
    int* arr_ptr = arr1;  // arr1 是数组名,指向 arr1 的首元素

    // 尝试修改数组名的地址(会报错)
    // arr1 = arr2;  // 错误:数组名是常量指针,不能重新赋值
	cout << "arr_ptr 第一次指向的数组元素: ";
	  for (int i = 0; i < 5; i++) {
	      cout << arr_ptr[i] << " ";
	  }
	  cout << endl;
    // 普通指针可以重新赋值
    arr_ptr = arr2;  // 正确:普通指针可以重新赋值,现在指向 arr2 的首元素

    // 输出数组元素
    cout << "arr1 的元素: ";
    for (int i = 0; i < 5; i++) {
        cout << arr1[i] << " ";
    }
    cout << endl;

    cout << "arr2 的元素: ";
    for (int i = 0; i < 5; i++) {
        cout << arr2[i] << " ";
    }
    cout << endl;

    cout << "arr_ptr 第二次指向的数组元素: ";
    for (int i = 0; i < 5; i++) {
        cout << arr_ptr[i] << " ";
    }
    cout << endl;

    return 0;
}

指针可以被重新赋值
这个例子中,指针和数组名都是可以通过自增自减来遍历数组的。

2.指针和数组在函数中的是如何应用的?

数组在函数中会被退化为指针:当数组作为函数参数时,传递的是数组的首地址。由于数组和指针在内存中的表示方式相似,C++ 允许数组名直接作为指针使用。
具体可以参考这个例子:

#include <iostream>
using namespace std;

// 函数声明
void printArray(int a[], int size);  // 数组作为参数!!!!重要!!!!
void printPointer(int* p, int size); // 指针作为参数

int main() {
    // 定义一个数组
    int arr[] = {1, 2, 3, 4, 5};
    int size = sizeof(arr) / sizeof(arr[0]);

    // 调用函数,数组退化为指针
    printArray(arr, size);

    // 定义一个指针,指向数组
    int* p = arr;

    // 调用函数,传递指针
    printPointer(p, size);

    return 0;
}

// 数组作为参数的函数实现
void printArray(int a[], int size) {
    cout << "数组中的元素: ";
    for (int i = 0; i < size; i++) {
        cout << a[i] << " ";
    }
    cout << endl;
}

// 指针作为参数的函数实现
void printPointer(int* p, int size) {
    cout << "指针指向的元素: ";
    for (int i = 0; i < size; i++) {
        cout << p[i] << " ";
    }
    cout << endl;
}

在这里,实参arr[ ],其实传递到函数printArray(int a[], int size)中,其实只是传递了a[0]的地址,也就是*a。

3. 数组与指针:不同写法,相同意义

在C++中,数组和指针的访问方式虽然形式不同,但本质上都是通过指针偏移来访问数组的第 i 个元素。例如,a[i]、i[a]、*(a + i) 和 *(i + a) 这些写法虽然形式不同,但它们的语义是相同的,都是访问数组的第 i 个元素。
数组中的第i个元素

4. 函数之间多维数组的传递

在C++中,多维数组可以通过指针传递给函数。由于多维数组在内存中是连续存储的,传递时需要指定数组的维度信息,以便函数能够正确地访问数组元素。
代码示例

#include <iostream>
using namespace std;

// 函数声明
void print2DArray(int arr[][3], int rows);  // 传递二维数组

int main() {
    // 定义一个二维数组
    int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};

    // 调用函数,传递二维数组
    print2DArray(arr, 2);

    return 0;
}

// 函数实现:打印二维数组
void print2DArray(int arr[][3], int rows) {
    cout << "二维数组的内容:" << endl;
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < 3; j++) {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}

当传递给 print2DArray 函数时,数组名 arr 会退化为指向其首元素的指针(即 int*)。由于是多维数组,函数参数需要指定数组的列数(如 int arr[][3]),以便函数能够正确地访问数组元素。在 print2DArray 函数中,通过双重for循环访问二维数组的每个元素。由于数组在内存中是连续存储的,函数可以通过指针运算正确地访问每个元素。多维数组的传递:需要指定数组的列数,以便函数能够正确地访问数组元素。数组名退化为指针:多维数组在传递时,数组名会退化为指向其首元素的指针。

相关文章:

  • 【11408学习记录】考研英语长难句解析 | 语法拆分+写作模板+真题精讲(附高分秘籍)
  • HTML5图片裁剪工具实现详解
  • LeetCode18四数之和
  • 【Redis】数据的淘汰策略
  • linux磁盘创建分区
  • 开源协议指南:主流许可证核心区别解析
  • 基于javaweb的SpringBoot汉服文化bbs系统设计与实现(源码+文档+部署讲解)
  • “Pseudo Global Warming”:伪全球变暖PGW
  • Diffusion-Based Planning for Autonomous Driving with Flexible Guidance论文细读
  • 【奇点时刻】GPT4o新图像生成模型底层原理深度洞察报告
  • 【Leetcode 994】腐烂的橘子 - 多源 BFS 解题思路与 Java 实现详解
  • Master节点重启k8s集群崩溃解决办法
  • AGI大模型(10):prompt逆向-巧借prompt
  • Windows 系统下安装 Docker
  • 构建网络 练习题三道
  • idea快捷键 Spring endpoint actions in the editor
  • Vue自定义指令最佳实践教程
  • 2022年蓝桥杯第十三届CC++大学B组真题及代码
  • Jmeter如何使用MD5进行加密?
  • 界面控件DevExpress WPF v25.1新功能预览 - AI功能增强
  • 营销网站报备/郑州网站关键词排名
  • 百度云做网站有优势吗/佛山快速排名seo
  • 四大网站是哪四大/全球最牛的搜索引擎
  • 泰安网络诈骗案件/seo优化排名工具
  • 做高性能的网站 哪门语言好/什么是网络营销推广
  • 网站管理的内容包括/台州seo公司