书籍使我变成了一个幸福的人,使我的生活变成轻松而舒适的诗。——高尔基

本文已经收录至我的GitHub,欢迎大家踊跃star 和 issues。

https://github.com/midou-tech/articles

点关注,不迷路!!!

前言

 我本来准备C语言章节就写个指针就ok了,在我看来C语言的精华部分就是指针了。但是有很多同学就开始在群里各种拉扯C语言的其他问题,没办法,我是龙叔嘛,想想还是整理一下,把一些重要的C语言知识点都一一更新了吧。C语言指针的内容请点击 指针(上)指针(下)记得点关注,不迷路

数组的基本概念

 我们把一组数据的集合称为数组(Array),它所包含的每一个数据叫做数组元素(Element),所包含的数据的个数称为数组长度(Length),数组中的每个元素都有一个序号,这个序号从0开始,而不是从我们熟悉的1开始,称为下标(Index),所包含数组的里面元素的类型叫做数组类型(Type)。

 一句话就说清楚了数组的基本概念,就是这么简单,^_^。

数组底层结构探析

1int array[5];

内存布局图


 不要看这个图简单,底层就是这样的。数组是一个整体,它的内存是连续的;也就是说,数组元素之间是相互挨着的,彼此之间没有一点点缝隙。

这一点很重要,连续的内存为指针操作(通过指针来访问数组元素)和内存处理(整块内存的复制、写入等)提供了便利,这使得数组可以作为缓存使用。

 有同学估计要说什么叫做指针操作,听龙叔絮叨下。

1int arr[5] = {1,2,3,4,5};
2printf("%d\n",arr[3]);

 看上面的代码,学过数组都知道arr[3]是取第三个元素的值,那我就要问你了,怎么取到值的呢???

 不要慌,龙叔告诉你其实就是指针操作。当我们声明并定义数组int arr[5] = {1,2,3,4,5},此时数组被分配了5个int大小的空间在栈上,并初始化了数组元素。我们都知道数组名代表数组的首元素的首地址,那么很明显就可以得到arr[3] = arr + 3。指针的加减操作详情请看龙叔公号,微信搜索 龙跃十二 即可订阅喔。


数组的运算

 1int a[] = {1,2,3,4};
2printf("%d\n",sizeof(a));
3printf("%d\n",sizeof(a+0));
4printf("%d\n",sizeof(*a));
5printf("%d\n",sizeof(a+1));
6printf("%d\n",sizeof(a[1]));
7printf("%d\n",sizeof(&a));
8printf("%d\n",sizeof(&a+1));
9printf("%d\n",sizeof(&a[0]));
10printf("%d\n",sizeof(&a[0]+1));
11//字符数组
12char arr[] = {'a','b','c','d','e','f'};
13printf("%d\n", sizeof(arr));
14printf("%d\n", sizeof(arr+0));
15printf("%d\n", sizeof(*arr));
16printf("%d\n", sizeof(arr[1]));
17printf("%d\n", sizeof(&arr));
18printf("%d\n", sizeof(&arr+1));
19printf("%d\n", sizeof(&arr[0]+1));
20printf("%d\n", strlen(arr));
21printf("%d\n", strlen(arr+0));
22printf("%d\n", strlen(*arr));
23printf("%d\n", strlen(arr[1]));
24printf("%d\n", strlen(&arr));
25printf("%d\n", strlen(&arr+1));
26printf("%d\n", strlen(&arr[0]+1));
27char *p = "abcdef";printf("%d\n", sizeof(p));
28printf("%d\n", sizeof(p+1));
29printf("%d\n", sizeof(*p));
30printf("%d\n", sizeof(p[0]));
31printf("%d\n", sizeof(&p));
32printf("%d\n", sizeof(&p+1));
33printf("%d\n", sizeof(&p[0]+1));
34printf("%d\n", strlen(p));
35printf("%d\n", strlen(p+1));
36printf("%d\n", strlen(*p));
37printf("%d\n", strlen(p[0]));
38printf("%d\n", strlen(&p));
39printf("%d\n", strlen(&p+1));
40printf("%d\n", strlen(&p[0]+1));
41//二维数组
42int a[3][4] = {0};
43printf("%d\n",sizeof(a));
44printf("%d\n",sizeof(a[0][0]));
45printf("%d\n",sizeof(a[0]));
46printf("%d\n",sizeof(a[0]+1));
47printf("%d\n",sizeof(a+1));
48printf("%d\n",sizeof(&a[0]+1));
49printf("%d\n",sizeof(*a));
50printf("%d\n",sizeof(a[3]));

就这几个运算,估计会难倒很多同学的,不信你可以把答案写出来之后在去跑一遍,全对找我拿红包


sizeof(数组名),代表整个数组的字节数;&数组名,代表取得整个数组的地址。

数组的一些特性

  1. 严格上说数组只有一维数组。n维数组是在一维数组里面存放一个(n-1)维数组,掌握以为数组即可。
  2. 数组的长度指的是数组的元素个数不是数组空间长度。sizeof()关键字即可获取数组总的字节数,在除以元素类型的字节数即可得到数组长度。
  3. C语言并不会判断数组访问越界,需要程序员判断越界访问。eg: int arr[5] = {1,2,3,4,5}; int b = arr[10];,这样访问也是可以拿到元素的,天知道你访问的是谁的数据。
  4. 数组底层内存结构是连续的。正是由于数组结构的连续性便诞生了内存的友好性,数组分配内存是整块分配的,堆内存很友好;连续的内存是的访问内存效率高。
  5. 数组大小是固定不变的。需要改变大小就需要新开一块大内存的数组,把之前的元素拷贝过来,释放之前的内存。
  6. 数据根据下标随机访问的时间复杂度为 O(1)
  7. 数据的插入和删除很低效:
  • 如果删除数组末尾的数据,最好情况时间复杂度为 O(1)
  • 如果删除开头的数据,则最坏情况时间复杂度为 O(n)
  • 平均情况时间复杂度也为 O(n)。

数组常见问题

数组长度是一个非常量。

1int b;
2scanf("%d",&b);
3int arr[3*b];

 不知道你曾经有没有写过这样的代码,反正我写过。数组的长度和内存是在程序编译时就已经确定了的。b的值是在运行时才确定的。有两个新名词,程序编译时&程序运行时

数组越界访问

1int arr[5] = {1,2,3,4,5};
2printf("%d\n",arr[-1]);
3printf("%d\n",arr[1]);
4printf("%d\n",arr[4]);
5printf("%d\n",arr[5]);
6printf("%d\n",arr[6]);

肉眼可见的错误,编译器竟然没报错。


数组相关笔试题目

  1. 给你一个数组,求一个k值,使得前k个数的方差 + 后面n-k个数的方差最小 ,时间复杂度可以到O(n)。
  2. 给定一个n个整型元素的数组a,其中有一个元素出现次数超过n / 2,求这个元素。
  3. 给定一个含有n个元素的数组,找出数组中的两个元素X和Y使得abs(x-y)最小。
  4. 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
  5. 在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
  6. 给定一个数组A[0,1,…,n-1],请构建一个数组B[0,1,…,n-1],其中B中的元素B[i]=A[0]A[1]A[i-1]A[i+1]A[n-1]。不能使用除法。(注意:规定B[0] = A[1] * A[2] * … * A[n-1],B[n-1] = A[0] * A[1] * … * A[n-2];)

利用数组可以出很多笔试题目,当然这些题目很多并不是考验数组本身特性大多是考算法基础的。本节就到这里了,有什么不清楚的问题欢迎留言喔,也可私信或mail。


「转发」是明目张胆的喜欢,「在看」是偷偷摸摸的爱。

往期精彩回顾:


《C语言》—— 数组详解的更多相关文章

  1. Java基础之 数组详解

    前言:Java内功心法之数组详解,看完这篇你向Java大神的路上又迈出了一步(有什么问题或者需要资料可以联系我的扣扣:734999078) 数组概念 同一种类型数据的集合.其实数组就是一个容器. 数组 ...

  2. “全栈2019”Java第三十一章:二维数组和多维数组详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  3. “全栈2019”Java第三十章:数组详解(下篇)

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  4. “全栈2019”Java第二十九章:数组详解(中篇)

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  5. “全栈2019”Java第二十八章:数组详解(上篇)

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. 深入理解C语言 - 指针详解

    一.什么是指针 C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址.CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位.这里,数据对象是指存储在 ...

  7. 3.awk数组详解及企业实战案例

    awk数组详解及企业实战案例 3.打印数组: [root@nfs-server test]# awk 'BEGIN{array[1]="zhurui";array[2]=" ...

  8. JavaScript进阶(十)Array 数组详解

    JS array 数组详解 数组的声明方法 arrayObj = new Array(); 的数组 ,并且第一位是5 数组的运算(传地址) var t2=new Array(); t2[0]=1; t ...

  9. Swift_数组详解

    Swift_数组详解 点击查看源码 初始化 //初始化 fileprivate func testInit() { //空数组 var array = [Int]() print(array) arr ...

  10. (转)awk数组详解及企业实战案例

    awk数组详解及企业实战案例 原文:http://www.cnblogs.com/hackerer/p/5365967.html#_label03.打印数组:1. [root@nfs-server t ...

随机推荐

  1. 关于Mach-O类型文件那点事

    Mach-O文件简介   Mach-O是一种文件格式,是Mach Object文件格式的缩写. 它通常应用于可执行文件,目标代码,动态库,内核转储等中.   Mach-O作为大部分基于Mach核心的操 ...

  2. Faster Rcnn训练自己的数据集过程大白话记录

    声明:每人都有自己的理解,动手实践才能对细节更加理解! 一.算法理解 此处省略一万字.................. 二.训练及源码理解 首先配置: 在./lib/utils文件下....运行 p ...

  3. MAVEN配置及Spring Tool Suite的Maven配置

    1.下载Maven http://maven.apache.org/download.cgi 如图点击下载即可 2.Maven配置 2.1配置本地仓库 创建目录maven-repository如图所示 ...

  4. Spring Boot2 系列教程 (十七) | 整合 WebSocket 实现聊天室

    微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 昨天那篇介绍了 WebSocket 实现广播,也即服务器端有消息时,将消息发送给所有连接了当前 endpoint 的浏览器.但 ...

  5. head查询

    • must子句:文档必须匹配must查询条件:• should子句:文档应该匹配should子句查询的一个或多个:• must_not子句:文档不能匹配该查询条件:• filter子句:过滤器,文档 ...

  6. gradle 不用打开项目直接编译

    gradlew :api-client:install 编辑完后点击

  7. Spring Boot 事务的使用

    Spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactio ...

  8. springcloud复习2

    Hystrix断路器 Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时.异常等,Hystrix能够保证在一个依赖出问题的情况下,不会导 ...

  9. Oracle Autonomous Health Framework (AHF) 解读

    AHF介绍 Oracle在2019年10月18日发布自治健康框架Autonomous Health Framework (AHF) 19.3,将ORAchk,EXAchk,TFA三种诊断工具合并入AH ...

  10. kubernetes concepts (一)

    Concepts The Concepts section helps you learn about the parts of the Kubernetes system and the abstr ...