0


【C语言】如何正确的理解数组 (一维)

哈喽大家好,我是保护小周ღ,C语言,接下来给大家带来的是数组和指针系列的文章,这篇主要讲的是一维数组的相关知识,是博主的所见所闻,细节上的知识后面会这里面没有提,会放在后期的文章中与指针相结合讲,多多包含。


一、 一维数组的创建和初始化

1.1 数组的创建

我们在程序开发中,常常需要描述一块由多个相同元素的数据项组成的数据,这就是数组。

数组:一组相同类型的元素的集合

数组的定义,举个例子:

int arr[5];

int 是指数组的元素类型,arr 是数组名, [ ] 可以先理解为告诉编译器这是个数组,里面的常量5 代表需要创建多少个 数组元素类型的元素。

这句话怎么站在编程的角度理解呢? 就是在内存的栈区上开辟一块连续的 5个 int 类型的空间(20个字节) ,然后这块空间名字叫 arr。

那我们是不是可以说 arr 的类型为 int [5] , 其实这才是正确的理解。

数组创建,在C99标准之前, [ ] 中 要给一个常量才可以,不能使用变量。在C99标准支持了变长数组的概念,数组的大小可以使用变量指定,但是数组不能初始化。VS 编译器中不支持变长数组,定义的时候只能是给常量。


1.2 数组的初始化

数组在定义创建的时候,我们可以对里面的值进行初始化。

C语言中数组不进行初始化的时候里面都是随机值。我们应该养成好习惯在定义的时候初始化将这些空间值置为0,int arr[5]={0}; 也可以根据自己的需要初始化值。

int arr0[5] = { 1,2,3,4,5 };

** 对数组的部分空间初始化:**

int arr1[10] = {1,2,3};

那么这一块10 个连续的整型空间前 3块空间的值分别初始化为 1,2,3;后面的7块空间都是随机值。


数组在创建的时候如果想不指定数组的确定的大小就得初始化。

int  arr[ ]={1,2,3,4,5};

这个时候编译器就会 根据初始化的内容来确定数组的元素个数,然后根据元素个数开辟空间。上例,初始化了5个元素,所以编译器会给 arr数组开辟5个 整型空间。


对字符数组的初始化:

首先字符数组也对根据初始的内容(元素个数)开辟相应的空间,只要是数组,在初始化的时候,如果你指定了数组的元素个数,但是你初始化的元素多于指定数组的空间个数,初始化的元素依次赋值给数组空间,多余的部分无效。

C语言里面没有字符串类型!通常用一个字符数组来存放一个字符串。字符数组每一块空间都只占1个字节。而且存储的内容是根据ASCLL码存储。

字符数组初始化的方式有两种:

依次的初始化(也可以指定字符数组的元素个数):

char str1[]={'a','b','c','d','e','f'};

存储结构如图:

这里给大家介绍一个概念,数组开辟的一块连续的存储空间,数组元素也是一种变量,通常称之为下标变量,我们可以通过数组的下标来表示,数组中的某一个元素。数组的下标规定从 0开始依次往后(详细内容后面讲)。

另外,在初始化的时候 char str1[ ]={ '97' , 97 }; 这两个的含义是不一样的,**' ' **引用表示用 ASCLL 码的形式存储,里面的数字会对应 ASCLL 表里字符存储。如果不打引号,这个数字就是单纯的数字,因为一个字节 是八个二进制位,如果是有符号位(signed)char 那么他的取值范围就是 [-128,127] , 无符号位(unsianed)char 取值范围就是 [0255] ,ASCLL码 规定由一个字节描述,最高位为 0 ,所以ASCLL 码的取值范围是 [0127] ,128个字符。 我们所说的 ‘\0’,其实就是 字符 0 ,但是千万不可以理解为 ‘0’,这个是数字0。


** 按照“字符串”元素个数开辟空间,和初始化:**

char str2[]="abcdef";

这种情况,表面上编译器为 str2 字符数组开辟6 个字节的空间,实际上是7个,因为编译器会把字符串的后一个空间放字符串的结束标志 ‘\0’ ,表示字符串已经结束。有了‘\0’标志后,编译器就可依此判断字符串的元素个数,所以使用字符串初始化的时候无须指定数组的长度。在输入,输出的时候还可以一次性处理字符串,可以不使用循环语句逐个输入和输出。(%s)字符串的形式。


二、 一维数组在内存中的存储

先来介绍一点知识,数组的使用,数组的 [ ] 是操作符,下标引用操作符,作用是就是可以访问数组元素, 数组名 [下标值] 即可访问对应下标的元素。

通过以上代码我们得出几点知识:

1. arr 就是数组名,数组名代表就是 数组首元素(下标为0 的元素)的地址,但是有两个例外

  • sizeof(数组名);计算的是整个数组的地址。
  • &数组名,数组名是表示整个数组,是取整个数组的地址。

sizeof 这个标识符的作用就是计算 它包含的在内存中所占的字节数。

所以我们计算一个整型数组的元素个数,可以用:sizeof (数组名) / sizeof(数组的任意一个元素);我们一般是 / 首元素。

**2. ** 栈区内存的使用习惯:先使用高地址处的空间,再使用低地址处的空间。

3. 假设 arr 数组在内存的栈区上开辟了一块连续的存储空间(40个字节),数组每个元素的地址根据数组的下标的增长,由低地址向高地址变化。

** 4. **数组在内存中是连续存放的

** 5.** 如果我们对定义的数组造成越界访问( 越界就是通过操作符等手段访问了不属于数组的空间),这种是很容易造成的错误,一定要注意,数组下标从 0 开始。没有初始化的空间往往就是随机值,也有可能是“烫烫烫”。


2.1 关于数组越界问题

  • 数组的下标是有范围限制的。
  • 数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。
  • 所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
  • C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的。

咱们写代码时,最好自己做越界的检查,一定要注意, 越界访问有可能就造成了对别的空间的非法使用,如果那块空间给到了某个变量维护,这就是很严重的错误。


2.2 关于字符数组计算元素个数的问题

上文说到字符数组的初始化有两种方式:

char str1[ ]={ 'a','b','c','d','e','f' };

char str2[ ]="abcdef";

我们先用sizeof 标识符来试试计算长度:

#include<stdio.h>
int main()
{
    char str1[] = {'a','b','c','d','e','f'};

    char str2[] = "abcdef";

    int len1 = sizeof(str1) / sizeof(str1[0]);
    int len2 = sizeof(str2) / sizeof(str2[0]);

    printf("str1数组的元素个数为:%d\n", len1);
    printf("str2数组的元素个数为:%d\n", len2);
    
    return 0;
}

这也证明了我们上文说的 如果直接初始化一个字符串,那么在字符串的最后还会使用一个空间存字符串的结束标志 '\0' ,在C语言当中 '\0'可是字符串里很重要的一点。我们在使用%s 以字符串的形式输入,其实最后编译器会默认在最后添加一个 '\0'; 使用 %s 以字符串的形式输出的时候,会根据 '\0' 来打印,'\0'之后的字符不会被打印。

举个例子:

scanf() 输入字符串:

我们可以看到我给 字符数组指定了10个字节的存储空间,理论上我们可以存10个字符,没有问题,但是我们是以字符串的形式输入,自己我输入了 10 个字符a 也打印出来了10个a 但是编译器报了个错,这是为什么呢?因为以字符串的形式存储,需要留一个空间存储 ‘\0’ 所以造成了越界使用空间,使用了 11个字节的空间,这样是不行的,所以我们给字符数组指定了空间大小(定义的时候),我们一定记得预留一个空间存储 ‘\0’ 。

错误得示范,越界访问时绝对不可以的, 越界使用更是大大得错误,一定要注意!

字符数组才可以整体得输入输出,整型数组,或者是浮点型数组,都得老老实实的循环输入输出!


我们使用 strlen ( ) 库函数来试试计算字符数组长度:

这里我们就很奇怪,str2 这个数组里,确实是 6个有效字符,没有问题,那么 str1 数组明明是只输入了 6个字符,为什么会有这个结果 19呢,好奇怪啊,接下来博主来给你们解答疑惑。

strlen( ) 这个库函数 专门计算字符数组的元素个数,那么他是根据 '\0'(字符串结束标志)来计算,遍历字符串,直到在内存中找到 '\0' 为止。返回类型是 无符号整型。

str1 字符数组,我们没有存放 '\0' 结束标志,所以在使用 strlen() 函数的时候就会越界访问,直到找到'\0' 。

不断地进行,越界访问,直到在内存中找到了 '\0' ,然后统计了 '\0' 之前的个数,这就是 strlen(str1)打印 19 原因,所以结束标志很关键得嘞。

当然解决方案就是:

char str[]={'a','b','c','d','e','f','\0'};

主动添加字符串结束标志,这就是争对循环输入字符的方式,手动末尾添加。


** printf() 打印字符串**

你们看咱们初始化的时候将 '\0' 其实就是字符0,放入str [ ]数组,没有问题,但是在打印的时候却忽略了 '\0' 后的字符 efg ,所以打印也是根据 '\0' 来决定打印的字符。


至此C语言一维数组博主已经分享完了,相信大家对一维数组有了不同的理解,尽请期待数组 &&指针。

本期收录于博主的专栏——C语言,适用于编程初学者,感兴趣的朋友们可以订阅,查看其它“C语言基础知识”。C语言_保护小周ღ的博客-CSDN博客

感谢每一个观看本篇文章的朋友,更多精彩敬请期待:保护小周ღ *★,°:.☆( ̄▽ ̄)/$:*.°★ **** **

文章多处存在借鉴,如有侵权请联系修改删除!

标签: c语言

本文转载自: https://blog.csdn.net/weixin_67603503/article/details/126802847
版权归原作者 保护小周ღ 所有, 如有侵权,请联系我们删除。

“【C语言】如何正确的理解数组 (一维)”的评论:

还没有评论