嵌入式开发学习日记——认识指针及和数组函数的联系(c语言)

一、指针的定义

一般格式

数据类型 * 指针变量名 [=初始地址值];

        数据类型是指针所指向的地址处的数据类型,如 int、char、float 等。

        符号 * 用于通知系统,这里定义的是一个指针变量,通常跟在类型关键字的后面,表示指针指向的是什么类型的值。比如,char  * 表示一个指向字符的指针,float * 表示一个指向浮点数的指针。

取址运算符和取值运算符

        取址运算符,使用 & 符号表示,作用是取出变量的内存地址。如果要格式化输出地址,需使用格式占位符 %p。

        取值运算符,使用 * 符号表示,作用是取出指针指向的内存地址处的数据值,也称为解引用运算符或间接引用运算符。

案例

通过指针修改所指向的值

#include <stdio.h>
int main()
{// 通过指针修改所指向位置的值double num = 2.88;// 创建指针变量p1指向num变量的地址double *p1 = &num;// 创建指针变量p2指向指针变量p1(p1中存储的是num变量的地址,所以p2中存储的也是num变量的地址)double *p2 = p1;printf("%.2f \n", num);*p1 = 3.88;printf("%.2f \n", num);*p2 += 10;printf("%.2f \n", num);return 0;
}

二、指针运算

1.指针加减整数

        指针与整数的加减运算,表示指针所指向的内存地址的移动(加,向后移动;减,向前移动),指针移动多少,与指针指向的数据类型有关,数据类型占据多少个字节,每单位就移动多少个字节,比如一个 int 类型指针,+1 向后移动 4 个字节,-2 向前移动 8 个字节。

        数组的元素在内存中连续存储的,我们通过数组元素来演示指针加减整数的情况。

代码如下:

#include <stdio.h>
int main()
{int nums[] = {10, 20, 30, 40, 50};int *ptr = &nums[0];// 打印指针变量ptr的值,和指针变量ptr指向的值printf("ptr = %p,*ptr = %d \n", ptr, *ptr);// ptr指针加3,指针变量ptr指向int类型,占4个字节,此时指针向后移动12个字节ptr += 3;printf("ptr = %p, *ptr = %d \n", ptr, *ptr);// ptr指针减2,指针变量ptr指向int类型,占4个字节,此时指针指向向前移动8个字节ptr -= 2;// 此时指针会向前移动8个字节printf("ptr = %p, *ptr = %d \n", ptr, *ptr);return 0;
}

2.指针自增自减

        指针自增、自减本质上就是指针加减整数,自增地址后移,自减地址前移。下面我们利用指针的自增自减实现数组的遍历,代码如下:

#include <stdio.h>
int main()
{short nums[] = {10, 20, 30, 40, 50};// 计算元素个数(数组长度)const int len = sizeof nums / sizeof nums[0];short *ptr = &nums[0]; // 定义short*类型的指针变量ptr指向nums数组中第一个元素的地址for (int i = 0; i < len; i++){printf("元素索引:%d,元素地址:%p,元素值:%d \n", i, ptr, *ptr);ptr++;}printf("=============\n");// 利用指针自减再次遍历数组// 此时指针超出数组界限,需先自减一次for (int i = len - 1; i >= 0; i--){ptr--;printf("元素索引:%d,元素地址:%p,元素值:%d \n", i, ptr, *ptr);}return 0;
}

3.同类型指针相减

在C语言中,指针相减的结果表示的是指针之间元素的个数。

当两个指针相减时,结果是通过计算两个指针所指向的元素之间的差异得到的。这个结果是一个整数,表示了两个指针所指向的元素在内存中的相对位置差异。具体来说,如果指针p指向数组a[i],指针q指向数组a[j],那么p-q的结果就等于i-j,即两个元素之间的索引差。这个结果是一个整数,其值取决于指针所指向的数据类型的大小。

例如,如果指针是指向字符类型的,那么相减的结果就是两个字符在内存中占用的字节数之差;如果指针是指向整数类型的,那么相减的结果就是两个整数在内存中占用的字节数之差。

需要注意的是,指针相减的结果会自动转化为整形,这是因为指针算术运算的结果类型是整数。这个转化是通过将指针之间的差异除以数据类型所占的字节数来得出的。例如,如果两个指针之间相差10个字节,而数据类型是字符型(每个字符占1个字节),那么相减的结果就是10;如果数据类型是整数型(每个整数占4个字节),那么相减的结果就是2(因为10除以4得到2余2,但结果会向下取整为2)。

此外,C语言支持3种格式的指针算术运算,包括指针加上整数、指针减去整数和两个指针相减。

相同类型的指针可以进行减法运算,返回它们之间的距离,即相隔多少个数据单位。高位地址减去低位地址,返回的是正值;低位地址减去高位地址,返回的是负值。

同类型指针相减的结果是一个 ptrdiff_t 类型数据,ptrdiff_t 类型是一个带符号的整数,格式输出中对应的格式占位符是 %td,相关案例如下:

#include <stdio.h>
int main()
{int nums[] = {10, 20, 30, 40, 50};// 定义指针变量指向数组中第一个元素的地址int *ptr1 = &nums[0];// 定义指针变量指向数组中第四个元素的地址int *ptr2 = &nums[3];printf("ptr2 - ptr1 = %td \n", ptr2 - ptr1); // 3 相差3个数据单位printf("ptr1 - ptr2 = %td \n", ptr1 - ptr2); // -3 相差3个数据单位// 定义两个指针相减double d1 = 1.0, d2 = 2.0;double *p1 = &d1, *p2 = &d2;printf("p2 - p1 = %td \n", p2 - p1); // -1 相差一个数据单位printf("p1 - p2 = %td \n", p1 - p2); // 1 相差一个数据单位return 0;
}

4.指针的比较运算

        指针之间可以进行比较运算,如 ==、<、 <= 、 >、 >=,比较的是各自指向的内存地址的大小,返回值是 int 类型整数 1 (true)或 0  (false)。案例演示如下:

#include <stdio.h>
int main()
{// 比较指针int nums[] = {10, 20, 30, 40, 50};double n = 1.0;// 定义指针变量指向数组第一个元素的地址int *ptr1 = &nums[0];// 定义指针变量指向数组第四个元素的地址int *ptr2 = &nums[3];// 定义指针变量指向数组第一个元素的地址int *ptr3 = &nums[0];// 定义指针变量指向变量n的地址double *ptr4 = &n;// 输出指针指向的地址printf("ptr1 = %p \n", ptr1);printf("ptr2 = %p \n", ptr2);printf("ptr3 = %p \n", ptr3);printf("ptr4 = %p \n", ptr4);// 比较printf("ptr1>ptr2 = %d \n", ptr1 > ptr2);printf("ptr1<ptr2 = %d \n", ptr1 < ptr2);printf("ptr1==ptr3 = %d \n", ptr1 == ptr3);// 由于是不同类型的指针进行比较,所以会有一个警告printf("ptr4>ptr1 = %d \n", ptr4 > ptr1);return 0;
}

三、指针和数组

1.指针数组

指针数组(Pointer Array)是一个数组,其中的每个元素都是指针。

语法规则:

数据类型 * 指针数组名 [长度];

示例代码:

#include <stdio.h>
int main()
{int num1 = 10, num2 = 20, num3 = 30;// 定义一个整型指针数组int *arr[3];// 指针数组中的每个元素指向不同的变量地址arr[0] = &num1;arr[1] = &num2;arr[2] = &num3;for (int i = 0; i < 3; i++){printf("%d,%p,%d \n", i, arr[i], *arr[i]);}return 0;
}

2.数组指针

数组指针(Array Pointer)是一个指针,它指向一个数组。注意,数组指针指向的是整个数组的地址而不是第一个元素的地址,虽然二者值是相同的,但在运算中会表现出不同。

语法规则:

数据类型 (*数组指针名)[长度]

示例代码:

#include <stdio.h>
// 数组指针:本身是一个指针,指向的是一个数组地址
int main()
{int arr[5] = {10, 20, 30, 40, 50};// 定义一个数组指针变量,指向数组(&nums就是整个数组地址)int(*ptr)[5] = &arr;// arr的类型是int *,ptr类型是int(*)[]// int *ptr2[5] = arr; // 报错,无效的初始值设定项// 二者值相同printf("%p \n", arr);printf("%p \n", ptr);// 数组指针指向的是数组的地址,而不是第一个元素的地址// 数组指针+1,会向后移动4*5=20个字节(整个数组的字节向后移动一倍),数组+1会向后移动4个字节printf("arr+1 = %p \n", arr + 1);printf("ptr+1 = %p \n", ptr + 1);for (int i = 0; i < 5; i++){printf("%d \n", (*ptr)[i]);}return 0;
}

数组指针和数组名的区别:

  1. 指向不同:数组名指向元素首地址,数组指针指向数组的地址。
  2. 类型不同:上面案例中,arr 的类型是 int[5],;ptr 的类型是 int(*)[5]。
  3. 可变性:数组名通常是不可变的;数组指针是可变的,你可以将它指向不同的数组。
  4. 初始化:数组名不需要显式初始化,它会自动指向数组的首元素;数组指针需要显式初始化,指定它将指向的数组。
  5. 访问元素:数组名访问数组元素不需要解引用;数组指针通常需要解引用才能访问数组元素。窗体顶端

四、指针和函数

1.传递指针给参数

当函数的形参类型是指针类型时,使用该函数时,需要传递指针、地址或者数组给该形参。

        传地址或指针给函数

        传数组给函数

数组名本身就代表数组首地址,因此传数组的本质就是传地址。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【C++笔记】string类深度解剖及其模拟实现

【C笔记】string类深度解剖及其模拟实现 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;C笔记 文章目录 【C笔记】string类深度解剖及其模拟实现前言一.string类说明1.1为什么实现string类1.2string类了解 二.string类的常用接口说明2.1str…

Nature Communications 英国伦敦大学等提出仿生自适应多平面触觉系统,实现机械与振动双重感知结合

触觉&#xff0c;作为人类感知外界并与之互动的重要方式&#xff0c;赋予了人类以辨识物体多重特性&#xff08;诸如纹理、硬度、可塑性及重量&#xff09;与捕捉微妙线索&#xff08;例如感知心跳或精准定位动脉振动&#xff09;的能力。这一感官机制不仅深化了人类对周围世界…

爬虫post请求

爬虫post请求 这一篇文章, 我们开始学习爬虫当中的post请求。 在讲post请求之前, 我们先来回顾一下get请求。 get请求: get请求的参数有三个, get(url, headers, params), 其中, params是可写可不写的。headers是请求头, 这个请求头在开发者工具里面的网络, 找到相应的请求, …

merlion的dashboard打开方法

安装好merlion包后&#xff0c;在anaconda prompt中进行如下图操作&#xff1a; 先进入创建好的虚拟环境&#xff1a;conda activate merlion再执行命令&#xff1a;python -m merlion.dashboard在浏览器中手动打开图中的地址&#xff1a; http://127.0.0.1:8050 打开后的界面…

Qt- QSS风格选择器常用属性选择器样式表盒子

1. 风格设置 Qt 提供了 3 种整体风格&#xff0c;使用 QStyleFactory::keys() 来获取 &#xff08;windowsvista 、Windows 、Fusion&#xff09; 可以在 main.cpp 中调用 setStyle 方法对应用程序进行全局风格的设置 int main(int argc, char *argv[]) {QApplication a(arg…

ElasticSearch+Kibana 8.1.0安装部署

Windows环境 通过百度网盘分享的文件&#xff1a;ElasticSearchKibanaik 链接&#xff1a;https://pan.baidu.com/s/14Bf9AkRjf5igaa10e18OWA?pwd1rmh 提取码&#xff1a;1rmh 下载后解压 命令都在bin目录下用cmd执行 一、ElasticSearch 注意&#xff1a;8.1.0自带jdk17&…

2024版51单片机教程

一、教程简介 前置基础

Linux云计算 |【第五阶段】ARCHITECTURE-DAY1

主要内容&#xff1a; 了解ELK分布式日志分析系统、Elasticsearch分布式集群搭建、Kibana搭建、使用kibana展示数据&#xff1b; 一、日志分析系统ELK概述 ELK 是 Elasticsearch、Logstash 和 Kibana 的缩写&#xff0c;是三款软件都是开源软件&#xff0c;通常是配合使用&am…

CentOS7安装Mysql5.7(ARM64架构)

1.第一步&#xff1a;下载 arm 版本离线 mysql 5.7 安装包 arm 版本离线 mysql 5.7 安装包 2.第二步&#xff1a;查询并卸载 CentOS 自带的数据库 Mariadb 找到数据库 mariadb&#xff0c;如果有会给出一个结果&#xff0c;结果是 mariadb 名称 rpm -qa | grep mariadb 如果…

64页精品PPT | 汽车经销商数据应用解决方案

汽车经销商正面临前所未有的盈利能力挑战。从18年起 &#xff0c;传统燃油车汽车行业开始步入低速增长阶段 &#xff0c;卖车已经挣不到钱 &#xff0c;利润往往来自任务完成的厂家返利&#xff1b;新兴的直营模式的出现 &#xff0c;冲击了传统授权经销的方式 &#xff0c;疫情…

matlab生成任意长度余弦波coe文件以及vivado仿真

一、matlab生成任意长度余弦波coe文件 clear clc close all width32; %rom的位宽 depth3600; %rom的深度 xlinspace(0,2*pi,depth); %在一个周期内产生3600个采样点 y_coscos(x); %生成余弦数据 y_cosround(y_cos*(2^(width-1)-1))2^(width-1)-1; %将余弦数据全部转换为…

用Eclipse运行第一个Java程序

1.左键双击在桌面“软件 (文件夹)”&#xff0c;打开该文件夹 2.左键双击“eclipse (文件夹)”&#xff0c;打开该文件夹 3.左键双击“eclipse (文件夹)”&#xff0c;打开该文件夹 4.左键双击“eclipse.exe”&#xff0c;运行这个可执行程序 5.左键单击“Ok&#xff08;按下按…

MySQL学习笔记(持续更新,目前到十一章锁)

1、Mysql概述 1.1 数据库相关概念 三个概念&#xff1a;数据库、数据库管理系统、SQL 名称全称简称数据库存储数据的仓库&#xff0c;数据是有组织的进行存储DataBase&#xff08;DB&#xff09;数据库管理系统操纵和管理数据库的大型软件DataBase Mangement System&#xf…

使用npm i报错node-sass失败问题解决

node 版本&#xff1a;v14.15.4 解决方法&#xff1a; npm config set sass_binary_sitehttps://npmmirror.com/mirrors/node-sass设置完之后&#xff0c;再npm i 就可以下载成功 亲测有效

视频汇聚平台EasyCVR支持云端录像丨监控存储丨录像回看丨录像计划丨录像配置

EasyCVR视频汇聚融合平台&#xff0c;是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。平台以其强大的视频处理、汇聚与融合能力&#xff0c;在构建视频监控系统中展现出了独特的优势。 EasyCVR视频汇聚平台可接入传统监控行业中高清网络摄像机的RTSP…

C++ | Leetcode C++题解之第475题供暖器

题目&#xff1a; 题解&#xff1a; class Solution { public:int findRadius(vector<int>& houses, vector<int>& heaters) {sort(houses.begin(), houses.end());sort(heaters.begin(), heaters.end());int ans 0;for (int i 0, j 0; i < houses.…

【Vue】Vue3.0 (十二)、watch对ref定义的基本类型、对象类型;reactive定义的对象类型的监视使用

上篇文章&#xff1a;【Vue】Vue3.0&#xff08;十一&#xff09;Vue 3.0 中 computed 计算属性概念、使用及示例 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Vue专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年10月16日12点45分 文章…

施磊C++ | 进阶学习笔记 | 5.设计模式

五、设计模式 文章目录 五、设计模式1.设计模式三大类型概述一、创建型设计模式二、结构型设计模式三、行为型设计模式 2.设计模式三大原则3.单例模式1.饿汉单例模式2.懒汉单例模式 4.线程安全的懒汉单例模式1.锁双重判断2.简洁的线程安全懒汉单例模式 5.简单工厂(Simple Facto…

2024-10-15 学习人工智能的Day7

在简单的了解完学习人工智能所需的高数、线代、概率论后&#xff0c;我们又重新开始了国庆的学习&#xff0c;因为已经有十余天没有接触python&#xff0c;所以今天的内容主要是对之前学习的python的回顾与总结&#xff0c;然后对各个部分进行了简单的实践&#xff0c;在最后学…

【无线技术】Wireless Technologies and Techniques——Antenna and Propagation

一、 天线基础 Introduction to Antenna 天线&#xff08;Antenna&#xff09;是一种设备&#xff0c;用于将电信号转换为无线电波进行传输&#xff0c;反之亦然&#xff08;用于接收&#xff09;。天线是所有无线系统的 “ 眼睛和耳朵 ” &#xff0c;负责电磁波的发射和接收。…