首页 > 其他分享 >三:指针在数组中的应用

三:指针在数组中的应用

时间:2024-08-14 15:27:49浏览次数:14  
标签:arr 数组 int 元素 应用 printf 指针

1. 使用指针访问数组

指针的加减运算可以用来在内存中移动指针的地址。加上一个整数 `n`,实际上就是移动了 `n` 个步长字节。步长是由指针指向的数据类型决定的。

例如,假设有一个 `int` 类型的指针 `p`:

int *p = (int *)100;


那么,执行 `p + 1` 后,指针地址会向后移动 `sizeof(int)` 字节(通常是4字节),即地址变为104。同样,执行 `p - 1` 后,指针地址会向前移动4字节,变为96。

这种加减运算对于访问在内存中连续排布的数据(比如数组)非常方便。

2. 使用第一个元素获取数组首地址

我们已经学会了使用下标访问数组元素:

#include <stdio.h>

int main() {
    int arr[5] = {111, 222, 333, 444, 555};
    printf("%d\n", arr[0]);
    printf("%d\n", arr[1]);
    printf("%d\n", arr[2]);
    printf("%d\n", arr[3]);
    printf("%d\n", arr[4]);
    return 0;
}

既然数组元素在内存中是连续排布的,第一个元素的地址就是整个数组的首地址。我们可以用取地址运算符 `&` 来获取第一个元素的地址:

int *p = &arr[0]; // 从第一个元素获取数组首地址

然后使用指针进行操作:

```
p;        // 指向第一个元素
p + 1;    // 指向第二个元素
p + 2;    // 指向第三个元素
p + 3;    // 指向第四个元素
p + 4;    // 指向第五个元素
```

通过取值运算符 `*`,可以访问或修改目标数据对象:

```
#include <stdio.h>

int main() {
    int arr[5] = {111, 222, 333, 444, 555};
    int *p = &arr[0];
    printf("%d\n", *p);       // 第一个元素
    printf("%d\n", *(p + 1)); // 第二个元素
    printf("%d\n", *(p + 2)); // 第三个元素
    printf("%d\n", *(p + 3)); // 第四个元素
    printf("%d\n", *(p + 4)); // 第五个元素
    return 0;
}
```

注意,表达式 `p + 1` 必须先用括号包裹起来,然后再用取值运算符 `*`。这是因为 `*` 的优先级高于加法运算符:

```
*(p + 1) // 正确
*p + 1   // 错误,这会对指针解引用的值再加1
```

 3. 使用数组名获取数组首地址

我们还可以通过数组名直接获取数组的首地址:

```
#include <stdio.h>

int main() {
    int arr[5] = {111, 222, 333, 444, 555};
    printf("arr = %u\n", arr);
    printf("&arr[0] = %u\n", &arr[0]);
    return 0;
}
```

`arr` 和 `&arr[0]` 都表示数组的首地址,那么我们可以直接将 `arr` 赋值给指针:

```
#include <stdio.h>

int main() {
    int arr[5] = {111, 222, 333, 444, 555};
    int *p = arr;
    printf("%d\n", *p);       // 第一个元素
    printf("%d\n", *(p + 1)); // 第二个元素
    printf("%d\n", *(p + 2)); // 第三个元素
    printf("%d\n", *(p + 3)); // 第四个元素
    printf("%d\n", *(p + 4)); // 第五个元素
    return 0;
}
```

虽然这些操作成功了,但这并不意味着数组名是一个指针。我们通过 `sizeof` 可以验证这一点:

```
#include <stdio.h>

int main() {
    int arr[5] = {111, 222, 333, 444, 555};
    int *p = arr;
    printf("sizeof arr = %d\n", sizeof(arr));    // 输出20
    printf("sizeof p = %d\n", sizeof(p));        // 输出4(假设是32位系统)
    printf("sizeof arr + 1 = %d\n", sizeof(arr + 1)); //输出4
    return 0;
}
```

数组名 `arr` 在代码中使用时,会被转换为指向数组第一个元素的指针。但在以下两种情况下不会:
1. 对数组名使用 `sizeof` 操作。
2. 对数组名使用 `&` 操作。

 4. 使用指针访问数组等价于下标访问

通过下面的例子,我们可以看到使用指针访问数组和使用下标访问数组是等价的:

```
#include <stdio.h>

int main() {
    int arr[5] = {111, 222, 333, 444, 555};
    printf("%d\n", arr[0]);      // 第一个元素
    printf("%d\n", arr[1]);      // 第二个元素
    printf("%d\n", arr[2]);      // 第三个元素
    printf("%d\n", arr[3]);      // 第四个元素
    printf("%d\n", arr[4]);      // 第五个元素
    printf("%d\n", *arr);        // 第一个元素
    printf("%d\n", *(arr + 1));  // 第二个元素
    printf("%d\n", *(arr + 2));  // 第三个元素
    printf("%d\n", *(arr + 3));  // 第四个元素
    printf("%d\n", *(arr + 4));  // 第五个元素
    return 0;
}
```

`arr[k]` 实际上会被编译器解读为 `*(arr + k)`。我们通过一个小测试来验证这个规则:

```
#include <stdio.h>

int main() {
    int arr[5] = {111, 222, 333, 444, 555};
    printf("arr[2] = %d\n", arr[2]);
    printf("2[arr] = %d\n", 2[arr]);
    printf("*(arr + 2) = %d\n", *(arr + 2));
    return 0;
}
```

运行结果验证了 `arr[2]` 和 `2[arr]` 是等价的,都是访问数组的第三个元素。

总结起来,我们学会了两种访问数组的方法:
1. `数组名[下标]`
2. `*(数组名 + 偏移量)`

这两种方式在功能上是完全等价的。

标签:arr,数组,int,元素,应用,printf,指针
From: https://blog.csdn.net/fang_xuan_xiang/article/details/141190700

相关文章

  • 【代码随想录】一、数组:3.双指针 - 977.有序数组的平方
    本文为977.有序数组的平方的解法,部分图文参考自代码随想录977.有序数组的平方。1.题目1:977.有序数组的平方1.1.解法1:直接排序classSolution{public:vector<int>sortedSquares(vector<int>&nums){for(inti=0;i<nums.size();i++){n......
  • 【代码随想录】一、数组:2.移除元素
    部分图文参考于:代码随想录-移除元素和力扣官方解法。1.题目1★:27.移除元素1.1.解法1:暴力解法考验对数组底层实现的理解:数组的元素是不能删的,只能覆盖。通过两层for循环来求解,外层for循环遍历数组元素,内层for循环将目标值进行覆盖。classSolution{public:intremove......
  • springboot+vue《区块链技术与应用》课程案例信息资源系统【程序+论文+开题】-计算机
    系统程序文件列表开题报告内容研究背景随着信息技术的飞速发展,教育领域正经历着前所未有的变革。区块链技术,作为新兴的去中心化、透明度高、安全性强的分布式账本技术,正逐渐渗透到各行各业,其在教育领域的应用潜力尤为巨大。当前,高校教学中案例资源的共享与管理面临着信息孤......
  • 【代码随想录】一、数组:1.二分查找
    部分图文参考于:代码随想录-二分查找,本文仅作为个人学习使用,如有侵权,请联系删除。1.概念二分查找也称折半查找(BinarySearch),是一种在有序数组中查找某一特定元素的搜索算法。我们可以从定义可知,运用二分搜索的前提是数组必须是有序的,这里需要注意的是,我们的输入不一定是数组,也......
  • BeanFactoryAware 在公司中的实际应用
    引言首先要先了解BeanFactoryAware是什么?BeanFactoryAware是Spring框架中的一个接口,它的作用是让某个Bean能够获得对BeanFactory的引用。这意味着该Bean在初始化过程中可以访问Spring容器中所有的其他Bean。这在某些情况下非常有用,特别是当一个Bean需要在运......
  • 【代码随想录】一、数组:理论基础
    原文链接:代码随想录-数组理论基础,本文仅作为个人学习使用,如有侵权,请联系删除。数组是非常基础的数据结构,在面试中,考察数组的题目一般在思维上都不难,主要是考察对代码的掌控能力。数组是存放在连续内存空间上的相同类型数据的集合。数组可以方便的通过下标索引的方式获取到下......
  • c语言转换char字符数组为大写小写
    #include<string.h>#include<stdlib.h>#include<stdio.h>#include<time.h>#include<ctype.h>#include<sys/stat.h>voidgetdate(char*datestr,char*format){ time_tnnowtime=time(NULL); structtm*ptmTemp=loc......
  • AWS多活容灾方案设计:IoT与移动应用的高可用架构
    1.引言在当今数字化时代,IoT设备和移动应用的无缝集成已成为许多企业的核心需求。然而,确保这些系统的高可用性和灾难恢复能力仍然是一个重大挑战。本文将详细探讨如何利用AWS的服务构建一个强大的多活容灾方案,特别关注IoT设备和移动应用必须在同一AWS区域内通信的特殊要求......
  • CFD中多孔介质计算及其工程应用
    1.多孔介质模型简介多孔介质模型主要用于模拟某空间内存在固相和气相或(及)液相的区域,以简化计算。简单来说,就是在原来很多细孔,管束,棒束等区域,采用简化模型,用纯流体区域代替这些复杂的区域。2.应用下面综合具体算例及其应用多孔介质的原因,进行分类说明本人见过的采用多孔介......
  • 面试官:说说volatile应用和实现原理?
    volatile是并发编程中的重要关键字,它的名气甚至是可以与synchronized、ReentrantLock等齐名,也是属于并发编程五杰之一。需要注意的是volatile并不能保证原子性,因此使用volatile并没有办法保证线程安全。并发编程五杰:PS:“并发编程五杰”是我个人起的名字,大家也不用太......