【嵌入式C语言】5.数组

前言

本章主要介绍数组相关内容。


  • 最近编码练习受益良多,个人建议荐逛博客学习的同时一定要多写代码多刷题,网上就有很多在线编码的网站。
  • 个人比较推荐在牛客网刷题(点击可以跳转),主要它登陆后会保存刷题记录进度,重新登录时写过的题目代码不会丢失,我觉得这一点还挺好的。
  • 个人刷题练习系列专栏:个人CSDN牛客刷题专栏
  • 牛客数组题目位置如下:
    在这里插入图片描述


1、数组是什么?

数组本质上是内存的一种分配形式。

  • 数组: 有序数据的集合,用数组名标识。
  • 数组是连续空间,空间属性:1.大小;2.读取方式。
  • 数组是一种建议符,而不是强制符。
  • 数组名的属性就是地址,数数组的首地址。
  • 元素: 属同一数据类型,用数组名和下标确定

2、数组的定义

数据类型 数组名[m];//m的作用域是在申请的时间,而指针的作用域是可变的
  • 数组名编译过后不可修改,是一个常量符号,一定不要放在“=”的左边。错误举例:
char buf[100];
buf="hello world!";//不可
//另例
buf++;//也不可,本质是buf=buf+1
  • 数组越界:指针访问的适合是可以越界的,因为m只作用在申请定义的时候,编译过后不起作用,举例:
int buf[10];
buf[100]=1;//可以,可以越界
buf[-10]=2;//可以,地址往下偏移
  • 但合法操作一般只在m内取值。

3、数组空间的初始化

3.1数组初始化

  • 空间的赋值:按照标签逐一处理。
  • 空间定义时,可就告知编译器的初始化情况,空间的第一次赋值,初始化操作。此步骤是交给编译器的,执行代码只能按照标签逐一处理。
  • C语言本身,CPU内部本身一般是不支持空间和空间的拷贝。只能按字节拷贝。
int a[10]=空间;
int a[10]={102030}//{}内容是一个空间块
=====>反汇编
伪代码: a[0]=10; a[1]=20; a[2]=10; a[3]=0或随机值;......//或调用标准库
  • 数组空间的初始化和变量的初始化本质不同,尤其在嵌入式的裸机开发中,空间的初始化往往需要库函数的辅助。

3.2char字符初始化

char buf[10]={'a','b','c'};//buf当成普通内存来看,这样赋值没有问题
//若当成一个字符串来看,不可以,最后需要加上'\0'或'0'
//字符串的重要属性,结尾一定有'\0'
char buf[10]={"abc"};//buf当成字符串最合理的写法,编译器自动加'\0'
char buf[10]="abc";//同上一样的;内存常量到变量的逐一拷贝
char *p="abc";//指向常量
buf[2]='e';//可以,改变数组(变量)内容
p[2]='e';//不可以,一定出现段错误,常量无法修改

在这里插入图片描述在这里插入图片描述

  • “abc"的” "是一段内存空间;400644是这一段内存的地址

3.3字符串空间(字符)

  • 字符空间:ASCII码编码来解释的空间。是为了给人看的。%s输出,人看是abc,计算机内存实际存的是’a’、‘b’、‘c’,编码方式是ASCII码。'\0’作为结束标志。是有符号位的。
char buf[10];//但这样定义一定为字符string
char buf[10] = "abc";
buf = "hello world"//错误
  • 第二次初始化只能只能逐一赋值;编译器只能解决第一次逐一处理的问题。
buf[0]= 'h’ buf[1] = 'e'... buf[n] = 'd', buf[n+1]= O;
  • 一块空间,当成了字符空间,提供了一套字符拷贝函数。
  • 字符拷贝函数的原则:内存空间和内存空间的逐一赋值的功能的一个封装体一旦空间中出现了0这个特殊值,函数就即将结束。
//strcpy(内存泄漏函数,若src无穷大,没\0,就会发生把内存泄漏,导致后续内存修改,程序跑飞)
char *strcpy (char *dest, const char src) ;
//strncpy (数量限制,不会造成内存泄漏)
char *strncpy (char *dest, constchar *src,size_t n);

举例:

char buf[10]= "abc";buf = "hello world";
strcpy(buf,"hello world");

3.4非字符串空间(数据)

  • 非字符空间:数据采集的值,最小单位0x00-0xff(8bit或8bit的倍数),在内存中开辟存储这些数据的空间。非字符空间是数据,数据是没有正负的,定义为无符号型变量:
unsigned char buf[10];//数据data,且是软件能处理的最小data,定义内存方式。(可能是字符,也可能是数据。一般认为是数据)
char buf[10];
buf="abc";//不可以,不能赋值空间块
unsigned char *p=sensor_base;
strcpy(buf,p);//不可以,strcpy执行时一定按字符处理,会寻找\0结束标志
  • 字符拷贝赋值只能逐一进行,非字符串的的结束标志是什么?非字符串只能定义个数。
  • 拷贝三要素:1.src,源地址;2.dest,目标地址;3.个数。
  • memcpy:内存拷贝。
void *memcpy(void *dest,const void *src,size_t n) ;

上例更正:

memcpy(buf,sensor,10*sizeof(int)) ;

举例:

unsigned char buf1[10];
unsigned char sensor_buf[100];// 00 00 00 23 45 78
strncpy(buf,sensor_buf,10);//错误,遇见0直接结束,不能正常拷贝
memcpy(buf,sensor_buf,10*sizeof(unsigned char));//正确

4、数组与指针

指针数组:

char* a[100];//* a[100]表示a里存放指针,数组里存了100个指针;char表示*读内存的方式,一个字节。
sizeof(a);//==100*4;100个的字节,(32位)
char **a;//多级指针,二维指针就相当于指针数组

5、多维数组及数组名的保存

  • 多维数组:是一种嵌套的数组。
  • 常见形式为:二维数组、三维数组…
  • 二维数组:是以一维数组作为数组元素的数组, 即“数组的数组”。
  • b[5][6];//在内存中读取方式:[5]是一个整体,[6]表示读取6次
//定义一个指针,指向int a[10]的首地址
int *p=a;
//定义一个指针,指向int b[5][6]的首地址
int **p=b;//错误,读地址的方式不一样

在这里插入图片描述在这里插入图片描述

int *p;//*修饰p,p就是地址了;int修饰*,是指指针的读取方法
int a;//int修饰a,是指a的读取内存方法
int a[5];//[5]说明a是数组;int修饰a,是a的读取内存方法;因此读取内存方法是5个int一起的读;与下一条相似
int (*p)[5];//(*p)与上述a相当于替换,*修饰p,p是指针(地址);因此读取内存方法是5个int一起的读;与上一条相似
int *p[5];//*修饰的是数组p,p是5个空间,里面存int*,内存方法是一个一个读;与前面两个不一样

更正及说明:

b[5][6];//[5]是一个整体,[6]表示读取6次

在这里插入图片描述

//进一步扩展为三维
int b[2][3][4];
int (*p)[3][4]=b;

结束语

  • 以上就是数组的内容,核心还是内存的操作,可以在牛客尝试刷几道数组题目检验。牛客网刷题(点击可以跳转),可以尝试注册使用。
    在这里插入图片描述

参考资料: 嵌入式C语言

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不僈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值