3-1 C指针与数组

前言:


基于本人回顾与思考,仅供学习参考


1.0 数组名称的用途

注:可以用于求数组占用的内存空间:sizeof(arrName);此时数组名称代表整个数组

cpp 复制代码
int32 t buffer[5]= {1,2,3,4,5};

int32 t size = sizeof(buffer);

printf("sizeof(buffer)= %d.\n",size);

运行以上程序输出如下结果:sizeof(buffer) = 20.


数组名称除了可以代表整个数组以外sizeof(buffer),还可以保存数组的首地址:buffer == &buffer0

这个用途应用在通过指针来访问数组,以及向函数传递数组的场景

cpp 复制代码
int32 t *p= buffer;

void Sort(int32 t buffer[])

数组名称是一种特殊的指针变量

cpp 复制代码
int8 t buffer[5]= {3,2,1,5, 4};

printf("buffer = %p.\n", buffer);

for (uint8 ti= 0;i< 5; i++)
{
    printf("&buffer[%d]= %p.\n", i, &buffer[i]);
    int8 t *ptr = buffer;
    printf("ptr = %p.\n", ptr);
}

运行以上程序输出如下结果:

数组名称buffer保存了数组的首地址,可以像指针变量一样直接读取地址值,不像结构

体等其他类型变量,需要使用&;


2.0 案例演示


cpp 复制代码
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "wifi_humi.h"

int main(void)
{
	uint8_t buffer[5]= {3,2,1,5,4};
	for (uint8_t i= 0; i< 5; i++)
	{
		printf("&buffer[%d]= %p.\n", i, &buffer[i]);
	}
	return 0;
}

通过bufferi来访问第i个元素,可以这样理解,将它分解为2个动作:

地址跳转到:首地址 +i * 步长 的地址,步长概念和讲解指针运算时步长概念一致,数据类型占用空间大小;buffer1也就是跳转到3F8+1*1(uint8 t步长为1)=3F9;

所以bufferi可以理解为在buffer保存的首地址基础上跳转i个步长**,访问buffer\[\]的内存空间,空间大小为数据类型大小,也即步长大小。**


3.0 指针数组访问



cpp 复制代码
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "wifi_humi.h"

int main(void)
{
	uint8_t buffer[5]= {3,2,1,5,4};
	uint8_t *p = buffer;
	for (uint8_t i= 0; i< 5; i++)
	{
		printf("*(p + %d)= %d.\n",i, *(p + i));
	}
	return 0;
}

运行以上程序输出如下结果:

既然数组名称里保存的是数组的首地址,所以可以配合*来访问数组元素:


4.0 指针作为数组使用


cpp 复制代码
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "wifi_humi.h"

int main(void)
{
	uint8_t buffer[5]= {3,2,1,5,4};
	uint8_t *p = buffer;
	for (uint8_t i= 0; i< 5; i++)
	{
		printf("*(p + %d)= %d.\n",i,p[i]);
	}
	return 0;
}

5.0 数组名称与指针变量的区别


数组名称第一种作用,可以代表整个数组:sizeof(数组名称)此时,数组名称代表整个数组;

数组名称的第二种作用,可以保存数组首地址 ,但是不需要像指针变量那样需要初始化赋值而且保存的地址数值是不能被改变的:


6.0 数组做为函数的参数



CalRawAvg(float data5,uint32 t len)

CalRawAvg(float datall, uint32 t len)

CalRawAvg(float data2,uint32 t len)


为什么float data\[\]和float data2这种方式也可以作为函数参数?

在C语言中,当你将一个数组作为参数传递给函数时,实际上传递的是该数组的首地址。因此,无论你在函数声明或定义中如何指定数组的大小,编译器都只接收指向数组第一个元素的指针。

这是因为当数组名被用作值时(例如,在作为函数参数传递时),它会自动"衰减"为指向其第一个元素的指针。这就是为什么float data\[\]和float data2都可以作为函数参数的原因------它们都被解释为float*类型的指针。

注:以下是一个简单的解释

实质上,数组作为参数,传递的并不是数组本身,而是数组的首地址,所以是地址传递,因

为数组不能像结构体那样进行整体赋值;不管是float data\[\]还是float data2,其实都等价于float *data,传参时发生的是:float*data = raw;

通常,定义函数时采用float *data或者floatdatal];既然传递的只是地址,所以需要增加一个参数用来表示数组的元素个数。


后记:

......

相关推荐
零依赖极客14 分钟前
Day 6·1 ARMv8.2 dotprod——vdotq_s32 一条指令做 4 个点积
c语言·开发语言·人工智能·矩阵·arm·vllm
stolentime20 分钟前
洛谷P10515 转圈题解
c++·算法·数学建模·贪心算法
和裕1 小时前
蜂窝板 vs 七层瓦楞重型纸箱:大件工业设备运输性能与成本全对比
大数据·运维·网络·人工智能·算法
衡石科技2 小时前
Data_Agent记忆机制与经验复用衡石分析智能体会话记忆与长期学习技术解析
人工智能·科技·学习·算法·企业级bi
新时代牛马2 小时前
cyclictest 毛刺从哪来?从ftrace、latencytop、perf到IRQ/调度延迟定位
android·开发语言·python·kotlin
三8442 小时前
Java 模板注入(FreeMarker) · 02 · 模板引擎与 FreeMarker 语法
java·开发语言·web安全·freemarker
IvanCodes2 小时前
Python 基础语法(七):推导式与常见遍历写法
开发语言·python
暮雨哀尘2 小时前
Java 基础练习(一):创建类并调用对象
java·开发语言
zhangzeyuaaa3 小时前
Python requests:raise_for_status() 与 4xx/5xx 异常层次详解
开发语言·python
泡海椒3 小时前
动态代理核心原理:JQuick-Java接口规则自动生成机制解析
java·开发语言·python