深入理解指针(c语言)

news2024/11/18 10:26:09

目录

  • 一、使用指针访问数组
  • 二、数组名的理解
      • 1、数组首元素的地址
      • 2、整个数组
  • 三、一维数组传参的本质
  • 四、冒泡排序
  • 五、二级指针
  • 六、指针数组

一、使用指针访问数组

可以使用指针来访问数组元素。例如,可以声明一个指针变量并将其指向数组的第一个元素,然后通过递增指针的方式来访问数组的其他元素:

#include<stdio.h>
int main()
{
    int arr[5] = { 1, 2, 3, 4, 5 };
    int* ptr = arr; // 指针指向数组的第一个元素

    for (int i = 0; i < 5; i++)
    {
        printf("%d ", *ptr); // 访问数组元素
        ptr++; // 指针递增,指向下一个元素
    }
    return 0;
}
  • 输出结果:
    在这里插入图片描述

二、数组名的理解

在C语言中,数组名有时代表数组中首元素的地址,有时代表整个数组,视情况而定。

1、数组首元素的地址

例1: 定义一个整型数组arr,可以用数组名arr表示数组的首地址,作为参数传递给函数:

#include<stdio.h>

void printArray(int arr[], int size) 
{
    for (int i = 0; i < size; i++) 
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

int main() 
{
    int arr[5] = {1, 2, 3, 4, 5};
    printArray(arr, 5);
    return 0;
}
  • 输出结果:
    在这里插入图片描述

这里,printArray函数的参数形式为int arr[],实际上是将数组名arr作为指针常量传递给函数。


例2: 用数组名访问数组中的元素:

#include<stdio.h>
int main()
{
	int arr[5] = { 1, 2, 3, 4, 5 };
	int* ptr = arr;
	printf("%d\n", *ptr);    // 输出1
	ptr++;
	printf("%d\n", *ptr);    // 输出2
	return 0;
}
  • 输出结果:
    在这里插入图片描述

这里,arr和ptr都指向数组的第一个元素,可以通过指针操作来访问数组的元素。


2、整个数组

例1: sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩(单位是字节):

#include<stdio.h>
int main()
{
	int arr[5] = { 1, 2, 3, 4, 5 };
	int size = sizeof(arr);
	printf("%d\n", size);
	return 0;
}
  • 输出结果:
    在这里插入图片描述
    例2: &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素的地址是有区别的)
#include<stdio.h>
int main()
{
	int arr[5] = { 1,2,3,4,5 };
	printf("&arr[0]   = %p\n", &arr[0]);
	printf("&arr[0]+1 = %p\n", &arr[0] + 1);
	printf("arr       = %p\n", arr);
	printf("arr+1     = %p\n", arr + 1);
	printf("&arr      = %p\n", &arr);
	printf("&arr+1    = %p\n", &arr + 1);
	return 0;
}
  • 输出结果:
    在这里插入图片描述
    这⾥我们发现&arr[0]和&arr[0]+1相差4个字节,arr和arr+1相差4个字节,是因为&arr[0]和arr都是⾸元素的地址,+1就是跳过⼀个元素。
    但是&arr和&arr+1相差20个字节,这就是因为&arr是数组的地址,+1操作是跳过整个数组的。

除了这两个例子之外,其他任何地⽅使⽤数组名都表⽰⾸元素的地址。

三、一维数组传参的本质

在C语言中,一维数组传参时,实际上传递的是数组的首地址,也就是数组名。函数可以通过修改传入的数组来修改实际的数据。

#include<stdio.h>

void modifyArray(int arr[], int size) 
{
    for (int i = 0; i < size; i++) 
    {
        arr[i] *= 2; // 修改数组元素
    }
}

int main() 
{
    int arr[5] = {1, 2, 3, 4, 5};
    modifyArray(arr, 5); // 传递数组名作为参数
    for (int i = 0; i < 5; i++) 
    {
        printf("%d ", arr[i]); // 输出修改后的数组
    }
    return 0;
}
  • 输出结果:
    在这里插入图片描述

四、冒泡排序

冒泡排序是一种基本的排序算法,通过多次比较和交换来实现。算法的核心思想是从数组的第一个元素开始,依次比较相邻的两个元素如果前一个元素大于后一个元素,则交换它们的位置

#include<stdio.h>

void bubbleSort(int arr[], int size) 
{
    for (int i = 0; i < size - 1; i++) 
    {
        for (int j = 0; j < size - i - 1; j++) 
        {
            if (arr[j] > arr[j + 1]) 
            {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

int main() 
{
    int arr[5] = {5, 4, 3, 2, 1};
    bubbleSort(arr, 5);
    for (int i = 0; i < 5; i++) 
    {
        printf("%d ", arr[i]);
    }
    return 0;
}
  • 输出结果:
    在这里插入图片描述

五、二级指针

二级指针是指向指针的指针。通过使用二级指针,可以在函数中修改指针的值,间接修改指针指向的变量。

#include<stdio.h>

void changeValue(int **ptr) 
{
    int newValue = 10;
    *ptr = &newValue; // 修改二级指针指向的变量
}

int main() 
{
    int value = 5;
    int *ptr = &value;
    changeValue(&ptr); // 传递二级指针作为参数
    printf("%d", *ptr); // 输出修改后的值
    return 0;
}
  • 输出结果:
    在这里插入图片描述

六、指针数组

指针数组是一个数组,其中的每个元素都是指针。通过指针数组,可以存储多个指针,并进行相应的操作。

#include<stdio.h>

int main() 
{
    int a = 1, b = 2, c = 3;
    int *ptrArray[3]; // 声明指针数组

    ptrArray[0] = &a; // 将指针赋值给数组元素
    ptrArray[1] = &b;
    ptrArray[2] = &c;

    for (int i = 0; i < 3; i++) 
    {
        printf("%d ", *ptrArray[i]); // 输出数组元素指向的值
    }

    return 0;
}
  • 输出结果:
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1462315.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Leo赠书活动-17期 《基础软件之路:企业级实践及开源之路》

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 赠书活动专栏 ✨特色专栏&#xff1a;…

基于深度学习的连锁酒店场景识别与部署实践指南

基于深度学习的连锁酒店场景识别与部署实践指南 项目背景与意义数据集介绍数据预处理与加载模型选择与开发模型选择模型训练模型评估测试 模型部署服务 项目背景与意义 在智能旅游行业&#xff0c;场景识别&#xff08;又称为场景分类&#xff09;是一个关键技术&#xff0c;它…

Autosar-CanIf模块介绍

4.1CanIf模块简介 CanIf模块是为了要隔离MCal层与服务层,因此CanIf不可直接操作硬件资源。然而CanIf传输数据、接收数据要使用到Can模块的缓存,如果直接使用Can模块的缓存的话,那CanIf就与MCal层耦合在一起了。 为了解决这个问题,CanIf层使用了一个HOH的概念:Hardware Obj…

情暖冬日团建——手拉手助成长社会融合实践活动

2月21日上午合肥六中高一&#xff08;14&#xff09;班团支部的曹文祥、储诚羲、杜尤扬、林彦锋、古胜宇、周文涛、许君昊、郭稷豪、吴彤、徐欣悦 、 褚福磊、高彦希、李柄杉、周子翔、高杨、姚子涵和高一&#xff08;3&#xff09;班孙锦宸、高一&#xff08;7&#xff09;班朱…

Istio实战:Istio Kiali部署与验证

目录 前言一、Istio安装小插曲 注意事项 二、Kiali安装三、Istio测试参考资料 前言 前几天我就开始捣腾Istio。前几天在执行istioctl install --set profiledemo -y 的时候老是在第二步就报错了&#xff0c;开始我用的istio版本是1.6.8。 后面查看k8s与istio的版本对应关系后发…

FIPS 140-3认证有什么重要性

FIPS 140-3&#xff0c;全称为《Federal Information Processing Standards Publication 140-3》&#xff0c;是美国联邦政府制定的一套关于加密模块的标准。该标准旨在确保加密技术在政府、军事和商业等领域的安全性和合规性。自1994年首次发布以来&#xff0c;FIPS 140-3已成…

【学习总结】慢SQL治理经验总结

一、慢SQL定义 执行超过1s的SQL为慢SQL 三、慢SQl的风险 系统的响应时间延迟&#xff0c;影响用户体验 资源占用增加&#xff0c;增高了系统的负载&#xff0c;其他请求响应时间也可能会收到影响。 慢SQL占用数据库连接的时间长,如果有大量慢SQL查询同时执行&#xff0c;可能…

人工智能讲师AI讲师大模型讲师叶梓介绍及大语言模型技术原理与实践提纲

叶梓&#xff0c;上海交通大学计算机专业博士毕业&#xff0c;高级工程师。主研方向&#xff1a;数据挖掘、机器学习、人工智能。历任国内知名上市IT企业的AI技术总监、资深技术专家&#xff0c;市级行业大数据平台技术负责人。 长期负责城市信息化智能平台的建设工作&#xff…

[ai笔记11] 论ai韭菜的自我修养

欢迎来到文思源想的ai空间&#xff0c;这是技术老兵学习ai以及观点分享的第11篇内容&#xff01; 上班之后时间确实少了许多&#xff0c;但是最近也没闲着&#xff0c;关于ai的学习一直在探索两个部分&#xff0c;一个是看那本有名的书《这就是ChatGPT》&#xff0c;另外一个则…

详细设计文档模版

背景 描述为什么要做这个技术改造&#xff0c;改造后收益是什么。可以是业务背景或者技术背景。 业务需求类此处可以将产品需求文档中的内容放到此处。技术改造类项目记录发起改造的原因&#xff0c;如系统问题、架构升级、bug修复、性能优化等。 现状 描述当前的技术实现的…

C#上位机与三菱PLC的通信09---开发自己的通讯库(A-3E版)

1、A-3E报文回顾 具体细节请看&#xff1a; C#上位机与三菱PLC的通信05--MC协议之QnA-3E报文解析 C#上位机与三菱PLC的通信06--MC协议之QnA-3E报文测试 2、为何要开发自己的通讯库 前面开发了自己的A-1E协议的通讯库&#xff0c;实现了数据的读写&#xff0c;对于封装的通…

合金电阻2512 0.01R是怎么应用在电池保护板中的

合金电阻2512 0.01R可以应用在电池保护板中的过流保护电路中。电池保护板用于监测和控制电池的充放电状态&#xff0c;以防止电池过充、过放和过流等情况&#xff0c;保护电池的安全和寿命。 过流保护电路是电池保护板的主要功能之一&#xff0c;用于检测电池输出电流是否超过安…

DT DAY3 信号和槽

作业&#xff1a; 1> 思维导图 2> 使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 btn3 new QPushButton("按钮3",this);btn3->resize(ui->btn2->width(),ui->b…

Android14 InputManager-InputReader的处理

IMS启动时会调用InputReader.start()方法 InputReader.cpp status_t InputReader::start() {if (mThread) {return ALREADY_EXISTS;}mThread std::make_unique<InputThread>("InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });…

第3.4章:StarRocks数据导入-Routine Load

注&#xff1a;本篇文章阐述的是StarRocks-3.2版本的Routine Load导入机制 一、概述 Routine Load&#xff08;例行导入&#xff09;支持用户提交一个常驻的导入任务&#xff0c;可以将消息流存储在 Kafka 的Topic中&#xff0c;通过订阅Topic 中的全部或部分分区的消息&#…

什么是EMC电磁兼容性测试?

摘要: 电磁兼容性测试&#xff08;Electromagnetic Compatibility Testing&#xff0c;简称EMC测试&#xff09;是对电子产品在电磁场方面干扰大小&#xff08;EMI&#xff09;和抗干扰能力&#xff08;EMS&#xff09;的综合评定。其目的是检测电器产品所产生的电磁辐射对人体…

代码随想录Leetcode 343. 整数拆分

题目&#xff1a; 代码(首刷看解析 2024年2月21日&#xff09;&#xff1a; dp[i]表示i所能拆分的最大乘积&#xff0c;则dp[i] 与dp[i - 1]的递推公式是&#xff1a; max( 1~n * dp[n ~ 1]) class Solution { public:int integerBreak(int n) {vector<int> dp(n 1);dp…

Python: argparse基本用法

Python: argparse基本用法 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;【Matplotlib之旅&#xff1a;零基础精通数据可视化】 &#x1f3c6;&#x1f3c6;关注博主&#xff0c;随时获取更多关于深度学习、PyTorch、Python领域的优质内容…

快速清理_卸载docker_找到不用的进程_centos磁盘爆满_清理磁盘---Linux工作笔记071

查看大文件,并且按照大小排名 cd / | du -h |sort -hr|head -30 可以看到根据不用的结果进行删除 可以看到在/data/dict目录很大,里面的都可以删除 然后再去卸载docker,要不然,没有磁盘是卸载不了的 systemctl stop docker systemctl stop docker.socket yum remove docker-…

DataX - 全量数据同步工具

前言 今天是2024-2-21&#xff0c;农历正月十二&#xff0c;相信今天开始是新的阶段&#xff0c;尽管它不是新的周一、某月一日、某年第一天&#xff0c;尽管我是一个很讲究仪式感的人。新年刚过去 12 天&#xff0c;再过 3 天就开学咯&#xff0c;开学之后我的大学时光就进入了…