嵌入式学习之路 14(C语言基础学习——指针操作一维整型数组)

news2024/9/24 11:30:39

一、指针基础

指针的概念

        地址表示内存单元的编号,也被称为指针。指针既是地址,也是一种专门用于处理地址数据的数据类型。
例如,变量a的地址或者十六进制表示的0x1000都可以视作指针。
 

指针变量的定义

语法:基类型 * 指针变量名。
        基类型可以是之前学过的各种数据类型,如整型、浮点型、字符型、结构体类型、函数类型等,它表示指针所指向的内存空间能够存放的数据类型。例如:int *p; 中,p就是一个指向整型数据的指针变量。
        *在定义时表示定义的是指针类型的变量。
        指针变量名需符合标识符命名规则。


指针类型

例如:在int *p;中,int *整体被称为指针类型,表示指向整型数据的指针类型。


指针变量的引用

例如:int a = 10; int *p = &a; ,p指向 a 。
*是指针运算符,为单目运算,运算对象只能是指针(地址)。
*p表示访问 p 所指向的基类型的内存空间,这是一种间接访问。其过程包括:首先拿出 p 中的地址,在内存中定位;然后偏移出 sizeof(基类型) 大小的一块空间;最后将偏移出的这块空间当作一个基类型变量来看。
例如,*p 的运算效果相当于直接访问的变量 a 。
类似地,对于int a; ,a的数据类型是 int ,&a的数据类型是 int* ,对于 float b; ,&b的数据类型是 float* 。


指针变量的初始化

如果指针变量没有初始化,此时的值是随机值(野指针)。
初始化可以让指针变量有明确的指向,例如:int a; int *p = &a; 或者 int *p = NULL(NULL 表示空指针,即 0 号地址)。


赋值

例如:int *p; p = &a;


定义多个指针变量

例如:int *p, *q; 表示定义了两个指针变量。
注意:定义时候的 * 是修饰变量名的,表示定义的是一个指针类型的变量。


为什么需要指针指针

指针可以实现被调函数修改主调函数中的数据。

二、指针作为函数的参数

1、形参是指针类型的变量,用来接收实参(实参是要操作的内存空间的地址)。
2、实参:要修改谁,就把谁的地址传进去,但要保证空间有效。
3、注意:被调函数中一定要有*p的运算(间接访问的操作)。
4、值传递只是实参数据赋值给了形参,而地址(指针传递)传递的是地址,可以实现被调修改主调。

练习:

#include <stdio.h>

// 函数:实现两个数相加,并将结果存储在指针所指的变量中
void ADD(int *a, int b) 
{
    *a = *a + b;  // 将指针 a 所指变量的值与 b 相加,并将结果存储回指针所指的变量
}

// 函数:找出两个数中的最大值和最小值,并通过指针返回
void maxandmin(int a, int b, int *max, int *min) 
{
    *max = a > b? a : b;  // 如果 a 大于 b,将 a 赋值给指针 max 所指的变量,否则将 b 赋值给它
    *min = a < b? a : b;  // 如果 a 小于 b,将 a 赋值给指针 min 所指的变量,否则将 b 赋值给它
}

// 函数:交换两个指针所指变量的值
void swap(int *a, int *b) 
{
    int temp = *a;  // 临时变量 temp 存储指针 a 所指变量的值
    *a = *b;  // 将指针 b 所指变量的值赋给指针 a 所指的变量
    *b = temp;  // 将临时变量 temp 的值赋给指针 b 所指的变量
}

// 主函数
int main() 
{
    int a = 2;  // 定义并初始化变量 a 为 2
    int b = 3;  // 定义并初始化变量 b 为 3

    int max;  // 定义变量用于存储最大值
    int min;  // 定义变量用于存储最小值

    // ADD(&a,b);  // 调用 ADD 函数,将 b 的值加到 a 上
    // printf("sum = %d\n",a);  // 输出相加后的结果

    // maxandmin(a,b,&max,&min);  // 调用 maxandmin 函数找出 a 和 b 的最大值和最小值
    // printf("max = %d, min = %d\n",max,min);

    printf("a = %d b = %d\n",a,b);  // 输出原始的 a 和 b 的值
    swap(&a,&b);  // 调用 swap 函数交换 a 和 b 的值
    printf("a = %d b = %d\n",a,b);  // 输出交换后的 a 和 b 的值

    return 0;
}

三、指针与一维整型数组

1、数组名代表数组首元素的地址,就是数组所在空间的首地址。例如:定义一个指向整型数组的指针变量可以写成 int *p = a; 或者 int *p = &a[0]; ,表示 p 指向了数组 a 。
2、数组名(数组首元素的地址)和 &a[0] 等价。
3、*p 等价于 a[0] 。
4、指针的运算:

&:取地址运算符。
*:解引用运算符。
p + 1:指针的算术运算,其偏移量取决于指针所指向的数据类型的大小。

指针的比较:

>  >=  <  <=  ==  !=

可以比较两个指针的大小或相等关系,但前提是这两个指针指向同一个数组或具有相同的基类型。

#include <stdio.h>

// 函数:打印数组元素
void printfArray(int *begin, int *end) 
{
    // 只要起始指针不超过结束指针,就持续执行循环
    while (begin <= end)  
    {
        // 打印起始指针所指向的元素,并将起始指针向后移动一位
        printf("%d ",*begin++);  
    }
    // 换行,使输出更清晰
    printf("\n");  
}

// 函数:找出数组中的最大值
int maxArray(int *a, int len) 
{
    int i;  // 定义循环变量
    // 初始化最大值为数组的第一个元素
    int max = *a;  

    // 遍历数组的每一个元素
    for (i = 0; i < len; i++)  
    {
        // 如果当前最大值小于数组中的某个元素
        if (max < *(a + i))  
        {
            // 更新最大值为该元素
            max = *(a + i);  
        }
    }

    // 返回最大值
    return max;  
}

// 函数:反转数组元素的顺序
void reversedOrder(int *begin, int *end) 
{
    int temp;  // 定义临时变量用于交换元素

    // 只要起始指针小于结束指针,就持续执行循环
    while(begin < end)  
    {
        // 交换起始指针和结束指针所指向的元素
        temp = *begin;  
        *begin = *end;  
        *end = temp;  
        // 起始指针向前移动一位
        begin++;  
        // 结束指针向后移动一位
        end--;  
    }
}

// 函数:选择排序
void choieSort(int *begin, int *end)  
{
    int *p = begin;  // 定义指向起始位置的指针
    int *q = NULL;  // 定义用于遍历的指针

    // 外层循环控制排序的轮数
    for (p = begin; p < end; p++)  
    {
        // 内层循环在每一轮中找出最小元素
        for (q = p + 1; q <= end; q++)  
        {
            // 如果当前元素大于后面的元素
            if (*p > *q)  
            {
                // 交换两个元素
                int t = *p;  
                *p = *q;  
                *q = t;  
            }
        }
    }
}

// 函数:冒泡排序
void bubbleSort(int *begin, int *end) 
{
    int *p = begin;  // 定义指向起始位置的指针
    int *q = NULL;  // 定义用于遍历的指针

    // 外层循环控制排序的轮数
    for (p = end; p > begin; p--)  
    {
        // 内层循环在每一轮中比较相邻元素
        for (q = begin; q < p; q++)  
        {
            // 如果当前元素大于下一个元素
            if (*q > *(q + 1))  
            {
                // 交换两个相邻元素
                int t = *q;  
                *q = *(q + 1);  
                *(q + 1) = t;  
            }
        }
    }
}

// 函数:插入排序
void insertSort(int *begin, int *end) 
{
    int *p = begin;  // 定义指向起始位置的指针
    int *q = NULL;  // 定义用于遍历的指针

    // 从第二个元素开始遍历
    for (p = begin + 1; p <= end; p++)  
    {
        int t = *p;  // 保存当前要插入的元素
        q = p;  // 记录当前位置

        // 寻找插入位置
        while (q > begin && *(q - 1) > t)  
        {
            // 将较大的元素向后移动
            *q = *(q - 1);  
            q--;  // 指针向前移动
        }
        // 插入元素
        *q = t;  
    }
}

// 函数:折半查找
int * binaryFind(int *begin, int *end, int n) 
{
    int *mid = NULL;  // 定义指向中间位置的指针
    int *ret = NULL;  // 定义用于存储查找结果的指针

    // 只要查找范围存在(起始指针小于等于结束指针)
    while (begin <= end)  
    {
        // 计算中间位置
        mid = begin + (end - begin) / 2;  

        // 如果要查找的值小于中间值
        if (n < *mid)  
        {
            // 在左半部分继续查找
            end = mid - 1;  
        }
        // 如果中间值小于要查找的值
        else if (*mid < n)  
        {
            // 在右半部分继续查找
            begin = mid + 1;  
        }
        // 如果找到匹配的值
        else  
        {
            // 记录找到的位置
            ret = mid;  
            break;  // 退出循环
        }
    }

    // 返回查找结果,如果未找到则为 NULL
    return ret;  
}

// 函数:折半查找(递归)
int *binaryFindR(int *begin, int *end, int n) 
{
    int *mid = begin + (end - begin) / 2;  // 计算中间位置
    int *ret = NULL;  // 定义用于存储查找结果的指针

    // 如果起始指针大于结束指针,说明未找到
    if (begin > end)  
    {
        return NULL;  
    }

    // 如果要查找的值小于中间值
    if (n < *mid)  
    {
        // 在左半部分递归查找
        end = mid - 1;  
        ret = binaryFindR(begin, end, n);  
    }
    // 如果中间值小于要查找的值
    else if (*mid < n)  
    {
        // 在右半部分递归查找
        begin = mid + 1;  
        ret = binaryFindR(begin, end, n);  
    }
    // 如果找到匹配的值
    else if (*mid == n)  
    {
        // 记录找到的位置
        ret = mid;  
    }

    // 返回查找结果,如果未找到则为 NULL
    return ret;  
}

// 函数:交换两个指针所指向的值
void swap(int *a, int *b) 
{
    int t = *a;  // 临时存储指针 a 所指向的值
    *a = *b;  // 将指针 b 所指向的值赋给指针 a 所指向的位置
    *b = t;  // 将临时存储的值赋给指针 b 所指向的位置
}

// 函数:快速排序
void quickSort(int *begin, int *end) 
{
    // 记录起始位置和结束位置
    int *p = begin;  
    int *q = end;  

    // 选择起始位置的元素作为基准值
    int *k = begin;  

    // 只要起始指针小于结束指针,就持续执行循环
    while (begin < end)  
    {
        // 从右向左找小于基准值的元素
        while(begin < end && *end >= *k)  
        {
            end--;  
        }

        // 从左向右找大于基准值的元素
        while (begin < end && *begin <= *k)  
        {
            begin++;  
        }

        // 交换找到的两个元素
        swap(begin, end);  
    }

    // 如果起始指针和结束指针相遇
    if (begin == end)  
    {
        // 将基准值与相遇位置的元素交换
        swap(k, begin);  
    }

    // 如果起始位置到结束位置减 1 的范围内还有元素,继续排序
    if (p < end - 1)  
    {
        quickSort(p, end - 1);  
    }

    // 如果起始位置加 1 到结束位置的范围内还有元素,继续排序
    if (begin + 1 < q)  
    {
        quickSort(begin + 1, q);  
    }
}

// 主函数
int main() 
{
    int a[] = {10,2,8,5,4,6,7,3,9,1};  // 定义并初始化整数数组
    int len = sizeof(a)/sizeof(a[0]);  // 计算数组的长度

    /*printf("max = %d\n",maxArray(a,len));

    printfArray(a,a+len-1);		//可以改变打印的起始位置和结束位置

    reversedOrder(a,a+len-1);
    printfArray(a,a+len-1);*/

    //choieSort(a,a+len-1);
    //bubbleSort(a,a+len-1);
    printfArray(a,a+len-1);
    //insertSort(a,a+len-1);
    //printfArray(a,a+len-1);

    /*int n;
    scanf("%d",&n);
    //int *ret = binaryFind(a,a+len-1,n);
    int *ret = binaryFindR(a,a+len-1,n);

    if (ret==NULL)
        printf("no found\n");
    else
        printf("found\n");
    */

    quickSort(a,a+len-1);  // 对数组进行快速排序
    printfArray(a,a+len-1);  // 打印排序后的数组

    return 0;
}

快速排序的思路 

5330fa9e787e422297929ba356da599e.png

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

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

相关文章

探索灵办AI:智能办公的好帮手

引言 随着AI工具的增多&#xff0c;选择合适的AI助手变得尤为重要。ChatGPT的订阅费用高且功能单一&#xff0c;很多小伙伴开始寻找更具性价比和多功能的替代品。灵办AI以其便捷、高效、多功能的特点&#xff0c;成为许多朋友的新宠。 灵办AI助手是一款多功能的全能AI助手&am…

智能名片信息交流系统应用场景解决方案

智能名片作为传统名片在数字化时代的进化产物&#xff0c;集成了移动互联网、大数据和人工智能等先进技术&#xff0c;为商务交流和客户关系管理带来了全新的体验。 系统主要功能 01内容聚合与展示 企业信息展示&#xff1a;智能名片不仅包含个人基本信息&#xff0c;还能展示…

MDIO C22协议访问MMD寄存器

以太网PHY芯片中SMI(Serial Management Interface)串行管理接口,也称MDIO(Management Data Input/Output),通常作为MII管理接口(MII Management Interface)。有两根线,分别为双向的MDIO和单向的MDC,用于以太网设备中上层对物理层(PHY)的管理。 MDIO接口有两种协议…

LVX+keepalived群集

Keepalived 双 机 热 备 基 础 知 识 Keepalived 起初是专门针对LVS 设计的一款强大的辅助工具&#xff0c;主要用来提供故障切换(Failover) 和健康检查(Health Checking) 功能——判断 LVS负载调度器、节点服务器的可用性&#xff0c;当master 主机出现故障及时切换到b…

MacOS Anaconda 安装教程及虚拟环境创建

一、下载 Anaconda 1、Anaconda 官网 2、清华大学开源软件镜像站 点 Date 按时间排序&#xff0c;根据自己 Mac 芯片类型下载对应最新版本的。 Intel 芯片的下载 x86_64 版本的Apple m1 芯片的下载 arm64 版本的 二、安装 Anaconda 将安装包下载到本地后&#xff0c;双击安…

人工智能|人工智能教育的发展现状及趋势

智能的热潮正席卷全球。国家在人工智能领域展开战略布局&#xff0c;人工智能人才成为国家急需的高层次技术人才。据领英发布的《全球 Al 领域人才报告》显示&#xff0c;国内人工智能人才缺口达到 500 多万。 毫无疑问&#xff0c;人工智能将不可阻挡地影响所有产业。给自己一…

随手记1.0

easyexcel多级表头导出各级设置样式&#xff08;继承HorizontalCellStyleStrategy实现&#xff09; package com.example.wxmessage.entity;import com.alibaba.excel.metadata.data.WriteCellData; import com.alibaba.excel.write.handler.context.CellWriteHandlerContext;…

探索 Amazon Q Developer 那些有趣的功能

我在 McKinsey 2024 年 5 月 30 日提供的一项名为“The state of AI in early 2024-Gen AI adoption spikes and starts to generate value”的调研中读到这么一句话&#xff1a;人工智能在组织中最常见的两个使用职能是&#xff1a;“市场营销和销售”以及“产品和服务开发”&…

vue3-ts:husky + prettier / 代码格式化工具

一、Prettier简介 Prettier是一个流行的代码格式化工具&#xff0c;它的主要作用是帮助开发者自动规范化代码的格式&#xff0c;提高代码的可读性和一致性。Prettier通过解析代码并使用自己的规则重新打印它&#xff0c;以确保代码风格的一致性和符合预设的格式化标准。 二、…

计网学习(四)——网络层

一、网际协议IP 互联网采用的设计思路&#xff1a;网络层向上只提供简单灵活的、无连接的、尽最大努力交付的数据报服务”&#xff0c;即IP数据报在网络中传输时是不可靠的服务&#xff0c;可能会出现数据丢失等情况TCP/IP体系中网络层常常被称为网际层或IP层与IP协议一起使用…

35分钟教你从0到1,水出SCI(精品),学术裁缝必修课_来自B站水论文的程序猿

系列文章目录 文章目录 系列文章目录一、抽象理解二、具体做法1、什么是Baseline(基础实验&#xff09;2、怎么和导师说3、怎么做压低baseline 4、怎么写 一、抽象理解 一篇论文A:西红柿炒鸡蛋 一篇论文B:芹菜炒肉 你就可以:西红柿炒肉 二、具体做法 1、什么是Baseline(基础…

视频压缩文件太大了怎么缩小?6个视频压缩技巧,速度收藏起来!

高清视频文件&#xff0c;尤其是那些以 1080p 和 720p 清晰度为特征的视频&#xff0c;通常都拥有相当大的体积&#xff0c;会占据大量计算机存储空间。因此&#xff0c;为了更好地将它们进行分享和存储&#xff0c;您可能需要对它们进行压缩&#xff0c;以减小它们的尺寸。然而…

【秋招笔试】2024-08-07-YT游戏(研发岗)-三语言题解(CPP/Python/Java)

🍭 大家好这里是 春秋招笔试突围,一起备战大厂笔试 💻 ACM金牌团队🏅️ | 多次AK大厂笔试 | 编程一对一辅导 ✨ 本系列打算持续跟新 秋招笔试题 👏 感谢大家的订阅➕ 和 喜欢💗 和 手里的小花花🌸 ✨ 笔试合集传送们 -> 🧷春秋招笔试合集 本次的题目比较典,…

资料分析6-其他类

一、拉动增长、增量贡献率和容斥问题 1. 拉动增长 拉动增长部分增量/整体前期&#xff0c;即x/A 例题1&#xff08;2018 年陕西&#xff09;&#xff1a;2017 年&#xff0c;我国电信业务收入12620 亿元&#xff0c;比上年增长6.4%&#xff0c;增速同比提高1 个百分点。……2…

递归:计算思维的核心

引言 人类对这个世界的认识是从特例到普遍&#xff0c;从具体到抽象&#xff0c;从简单到复杂的&#xff0c;是一个递推&#xff08;Iterative&#xff09;的过程。这种人类固有的认知与思维方式令我们可以轻易的理解具体的事物&#xff0c;但同时却限制了我们的抽象能力和大局…

【电控笔记z6】无感文献综述

高频注入 afabeta注入 lq/ld越大统好 凸极性大反电动势ZVCD pwm电压向量为主 增加动态特性 设计隆博戈估测器 高频注入: lq/ld比较大 运用在低转速 到高速的时候 , 切换到model_base的方法进行反电动势侦测 smo :速度无法很低 有个极限 受杂讯影响大 高速时候用 总结 用spm …

ArrayList集合源码解读(一)

ArrayList集合源码解读&#xff08;一&#xff09; 前言 笔者在阅读网上众多的ArrayList源码解读时发现他们都是以1.8版本的来进行讲解&#xff0c;并且很多都是囫囵吞枣&#xff0c;看的人一脸懵逼。 其实现在的很多公司都换成了17版本的jdk。笔者决定自己写一个ArrayList集…

网工内推 | 国企运维工程师,华为认证优先,最高年薪20w

01 上海陆家嘴物业管理有限公司 &#x1f537;招聘岗位&#xff1a;IT运维工程师 &#x1f537;岗位职责&#xff1a; 1、负责对公司软、硬件系统、周边设备、桌面系统、服务器、网络基础环境运行维护、故障排除。 2、负责对各部门软件操作、网络安全进行检查、指导。 3、负责…

14.Lambda表达式、可变参数

一.Lambda表达式 1.1 函数式接口 1.什么是函数式接口 在Java中&#xff0c;函数式接口是指只包含单个抽象方法的接口&#xff0c;但它也可以有其他方法&#xff0c;例如默认方法和静态方法。函数式接口可以使用Lambda表达式或方法引用来创建该接口的实例。Java 8引入了函数式…

分享一个基于SpringBoot的大学生创新能力培养平台Java(源码、调试、LW、开题、PPT)

&#x1f495;&#x1f495;作者&#xff1a;计算机源码社 &#x1f495;&#x1f495;个人简介&#xff1a;本人 八年开发经验&#xff0c;擅长Java、Python、PHP、.NET、Node.js、Android、微信小程序、爬虫、大数据、机器学习等&#xff0c;大家有这一块的问题可以一起交流&…