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

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

   image.gif编辑

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

image.gif编辑

目录

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

1.1 数组的创建

1.2 数组的初始化

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

2.1 关于数组越界问题

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


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

1.1 数组的创建

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

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

数组的定义,举个例子:

int arr[5];

image.gif

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 };

image.gif


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

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

image.gif

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


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

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

image.gif

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


对字符数组的初始化:

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

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

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

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

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

image.gif

存储结构如图:image.gif编辑

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

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

image.gif编辑


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

char str2[]="abcdef";

image.gif

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

image.gif编辑


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

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

image.gif编辑

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

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

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

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

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

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

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

    image.gif编辑

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

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


    2.1 关于数组越界问题

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

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

      image.gif编辑


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

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

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

      char  str2[ ]="abcdef";

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

      #include<stdio.h>intmain()
      {
      charstr1[] = {'a','b','c','d','e','f'};
      charstr2[] ="abcdef";
      intlen1=sizeof(str1) /sizeof(str1[0]);
      intlen2=sizeof(str2) /sizeof(str2[0]);
      printf("str1数组的元素个数为:%d\n", len1);
      printf("str2数组的元素个数为:%d\n", len2);
      return0;
      }

      image.gif

      image.gif编辑

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

      举个例子:

      scanf() 输入字符串:

      image.gif编辑

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

      image.gif编辑

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

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


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

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

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

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

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

      当然解决方案就是:

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

      image.gif

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


      printf() 打印字符串

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


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

      image.gif编辑

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

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

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

      相关文章
      |
      21天前
      |
      存储 编译器 C语言
      【c语言】数组
      本文介绍了数组的基本概念及一维和二维数组的创建、初始化、使用方法及其在内存中的存储形式。一维数组通过下标访问元素,支持初始化和动态输入输出。二维数组则通过行和列的下标访问元素,同样支持初始化和动态输入输出。此外,还简要介绍了C99标准中的变长数组,允许在运行时根据变量创建数组,但不能初始化。
      35 6
      |
      24天前
      |
      存储 算法 C语言
      C语言:什么是指针数组,它有什么用
      指针数组是C语言中一种特殊的数据结构,每个元素都是一个指针。它用于存储多个内存地址,方便对多个变量或数组进行操作,常用于字符串处理、动态内存分配等场景。
      |
      30天前
      |
      存储 人工智能 BI
      C语言:数组的分类
      C语言中的数组分为一维数组、多维数组和字符串数组。一维数组是最基本的形式,用于存储一系列相同类型的元素;多维数组则可以看作是一维数组的数组,常用于矩阵运算等场景;字符串数组则是以字符为元素的一维数组,专门用于处理文本数据。
      |
      28天前
      |
      存储 C语言
      C语言:一维数组的不初始化、部分初始化、完全初始化的不同点
      C语言中一维数组的初始化有三种情况:不初始化时,数组元素的值是随机的;部分初始化时,未指定的元素会被自动赋值为0;完全初始化时,所有元素都被赋予了初始值。
      |
      1月前
      |
      存储 数据管理 编译器
      揭秘C语言:高效数据管理之数组
      揭秘C语言:高效数据管理之数组
      |
      1月前
      |
      C语言 C++
      保姆式教学C语言——数组
      保姆式教学C语言——数组
      16 0
      保姆式教学C语言——数组
      |
      1月前
      |
      C语言
      数组栈的实现(C语言描述)
      本文介绍了如何在C语言中使用数组来实现栈的数据结构,包括栈的创建、入栈、出栈、获取栈顶元素、检查栈是否为空、获取栈的大小以及销毁栈等操作,并提供了相应的函数实现。
      23 1
      |
      1月前
      |
      C语言
      顺序表数组法构建(C语言描述)
      如何使用C语言通过数组方法构建有序顺序表,包括顺序表的创建、插入、删除和打印等。
      16 2
      |
      1月前
      |
      存储 编译器 C语言
      【C语言】数组(一维、二维数组的简单介绍)
      【C语言】数组(一维、二维数组的简单介绍)
      |
      30天前
      |
      C语言
      C语言数组
      C语言数组
      16 0