数组定义方式类型名指向存储数据的首地址

 2024-01-05 10:13:58  阅读 0

数组定义方法

输入数组名称[数组大小]; //类型为每个空间的大小。 我们通过数组名和下标来访问数据。 数组名指向存储数据的首地址,但我们无法更改数组名指向的地址。 数组大小只有在定义时才生效,定义后不能更改。

int a[100]; //申请了一个名叫a的数组,它包含了100个整型。

数组访问

我们可以通过数组的下标来访问数据。 C不会检查我们的下标是否合格,就像指针不会检查越界一样。 不能对数组名进行加减运算,比如a++等,这相当于打算改变它指向的首地址,这在C中是不允许的。

数组空间的初始化

数组空间的初始化就是给每个标签地址赋值。 请一一遵循标签。 如果我们需要给每个内存赋值,如果有一个int a[100]; 我们需要使用下标来给100个int类型空间赋值。 这种工作量是非常大的,所以我们想到了让编译器做一些初始化操作。 初始化操作是第一次赋值,第二次赋值不能这样进行。

int a[10]=空间;

我需要给它一个空间来批量处理里面的值​​​​; 例如,int a[10]={10,20,30}; //a[1]=10,a[2]=20,a[3]=30,a[4]=…=a[9]=0,所以实际上是批量内存复制的结果,而未赋值的结果是0。初始化和一一赋值一样高效。 批量复制仅限于第一个作业。

注意:数组空间的初始化和变量的初始化有本质的区别。 尤其是嵌入式裸机开发中,空间的初始化往往需要库函数的协助。

char buf[10]={'a','b','c'}; //c的字符串有一个重要的属性,字符串结尾有一个字符'\0'代表字符串的结束。因为我们这里为字符串空间定义了10个字符的大小,但是有时候我们并没有使用完这10个字节,打印的时候10个字节的打印也是错误的,所以为了给字符串一个结束的标志,让其它的函数比如printf函数输出的时候知道它的结尾。
char buf[]="abc";  //省略数组大小,C会为数组指定大小,这里就是三个字符加上一个结尾标志,数组大小就是4
char buf[10]={"abc"};
char buf[10]="abc";  //将三个字符批量拷贝到它分配的空间,末尾加'\0'
char *p="abc"; //先给三个字符分配空间,再将指针指向字符串的首地址,这指向的是一个常量字符串。
buf[2]='e';  //这是可以的
p[2]= 'e';  //这是不可以的,p指向的是常量区

测试代码如下

我们使用这个字符串作为函数的参数,它返回的实际上是常量字符串的首地址,我们在这里将其打印为整数。 有警告,应将其作为无符号整数(内存地址为正整数)来打印。

#include 
int main(){
      printf("the %x\n", "abc");
}

运行结果如下

the 404000

可以看到确实打印了一个地址,说明双引号返回的是一个地址,这和我们前面介绍的字符数组获取它的首地址然后顺序复制是一模一样的,只不过字符指针直接获取它的地址地址存储。 这些不同的操作是特定于数据类型的操作。

C语言数组初始化高级数组空间初始化

char buf[10]="abc";
a="Hello World";

我们知道双引号中的字符串是常量。 系统为它们分配空间后,会尝试将第一个内存地址分配给数组名。 正如我们之前所说,存储数组名的首地址不能更改。 由于之前已经初始化过,数组名指向的地址已经确定,所以不能再次赋值。

数组的第二次内存分配只能给它们一一赋值,如下:

buf[0]='h'; buf[1]='e';  ……   buf[n]='d';  buf[n+1]=0; //结尾标志

字符复制功能的原理:内存空间的封装以及对内存空间一一赋值的功能。 一旦空格中出现结束标志0,则函数即将结束。

:在终端中输入 man 查看函数声明。 声明此函数时,源字符串是常量字符串,而目标字符串不是常量字符串。 这是常识,毕竟我们复制这个字符串并没有改变它的值。 该函数接收两个字符串指针,并将源地址的内容一一复制到目的地址。 当遇到源字符串的结束标志 0 时,复制结束。

我们可以想象一个函数的模板:

int i=0;
while(src[i]!='\0') {
      dest[i] = src[i];  
      i++;
}

c语言数组输出_输出数组c语言_c语言输出数组用什么字母

随着硬件的升级,硬件已经能够帮我们做一些事情了,所以有些代码就带有一些汇编语言,而汇编语言可以进一步提高功能的效率。 所以如果我们面试嵌入式开发工程师,面试官可能会要求你写一个标准函数。 可以按照上面的形式写,也可以根据CPU架构和能力加一句。 不同的是,这个程序是可以优化的。 当我们以后看到具体的CPU和核心时,我们就会明白为什么这并不像我们想象的那么简单。 我们只能猜测它的用途,但具体实现细节不一定是上面的函数代码。

此时我们可以简单地给buf赋值即可。

strcpy(buf,"hello world"); //将hello world这个字符串拷贝到buf中,并自动在结尾加上结束标志0。

该函数可能会导致内存泄漏。 如果黑客使用很长的字符串作为源字符串复制到内存中,则函数只有遇到源字符串的结束标记时才会停止复制,并且可能会覆盖内存中的原始字符串。 数据,导致很多问题。 我们在项目中不允许使用这个功能。 我们正在使用此函数,它提供第三个参数并接受副本大小值。 此时只会复制这么多字符,不会造成内存泄漏。

C语言数组初始化实际数组空间初始化

字符空间是我们操作的最小空间。 int类型、float类型、结构体类型也有空格。 这些类型的要求没有字符空间那么多。 字符空间涉及到字符串和结束标记的概念。 接下来我们要介绍的是非字符空间。

字符空间:可以使用ASCII码解码的空间。 我们可以理解并使用%s来查看。 \0 是结束标识符。

非字符空间:例如物联网中的数据采集、室内燃气安全、照明、温度检测等。采集到的数据以8位或8位的倍数存储。 这些数据没有符号或 ASCII。 代码。 如果我们想存储这些数据,我们需要使用char buf[10]。 我们可以使用字符串直接复制温度传感设备中的数据吗? 显然这是不可能的,因为温度传感设备中的数据不是存储的字符串。 如果没有结束标记,就会不断地复制,从而导致内存泄漏。

为了实现非字符空间的复制,C为我们提供了一个新函数。

void *memcpy(void *dest, const void *src, size_t n);

它有三个参数,目标地址、源地址和复制字节。 int类型占用4个字节,所以下面复制的字节应该是40个字节。

int buf[100];
int sensor_buf[100];
memcpy(buf, sensor_buf, 10*sizeof(int));

看起来参数和是一样的,但是他们的内部实现机制是不一样的。 如果我们在存储的数据中使用\0结束字符,则复制会提前中断。 注意:第三个参数传递的是字节数,而不是类型数。 标准写法应该是数字*(类型);

字符空间和非字符空间都是我们要考虑的。 C语言的目的是操作资源,而这些资源就是内存中的数据。 在随后的面试过程中,面试官问了我们一些问题。 首先我们先找到题中的操作对象,区分是字符类型还是非字符类型。 其次,我们会讲一下如何操作,比如加、减、乘、除等,这是面试的原理。 不要把它想得太复杂。

C语言指针数组概述 指针数组概述

熟悉了数组空间的概念后,我们知道int a[100]存储的是int类型数据。 如果其中存储的是地址,那么这是一个指针数组。 指针值是存储在数组中的指针。 我们定义指针数组如下;

char  *a[100]; //a存放了100个指向char类型的指针

从(a)可以看出,其100个指针变量的大小为100*4(4为指针变量的大小)。 指针数组与二维指针非常相似。 但他们的区别可以从下图中看出。

C语言数组名指针保存数组名指针保存

定义一个指向int a[10]首地址的指针:

int *p=a;

对于int类型的数组和指针,读取方法是一样的,都是以四个字节为单位读取。 所以这个赋值方法是正确的。

定义一个指向int b[5][6]首地址的指针

我们不能使用像 int p=b 这样的二维指针来赋值。 我们先来分析一下为什么结果是错误的。 读取二维数组时是逐行读取,而二维指针读取的是线性表。 当我们定义一个char *p的时候,我们就明白读取的方式是char类型。 但现在需求不同了,不再是简单的char类型读取方式。

我们知道 int a[6]; a一次读取6个int类型,所以现在我们需要指针能够这样读取,用一个指针变量来代替这个普通变量。 有如下定义:

int (*p)[6]=b;

[] 的优先级高于 *。 添加括号后,就定义了一个指向二维数组的指针p。 p指向二维数组的首地址。 P[1]指向第二行的首地址。 现在以p为单位,一次读取6个int类型数据。 P[1][1]指向第二行第二列的数据。 前面的p[1]返回第一行的首地址,后面的[1]表示再移动一个单位。 这是int类型的大小,移动了4个单位。

标签: 数组 字符 指针

如本站内容信息有侵犯到您的权益请联系我们删除,谢谢!!


Copyright © 2020 All Rights Reserved 京ICP5741267-1号 统计代码