为了让大家更好地学习和理解数组,我们先来认识一下内存中的"地址"。

地址

1.计算机中的内存是以字节为单位的存储空间。内存的每一个字节都有一个唯一的编号,这个编号就称为地址。凡存放在内存中的程序和数据都有一个地址,也就是说,一个函数也有自己的内存地址。

2.当定义一个变量时,系统就分配一个带有唯一地址的存储单元来存储这个变量。比如:

char a = 'A'; // A的ASCII值为65

int b = 66;
在16bit编译器环境下,系统为a、b分别分配1个字节、2个字节的存储单元。变量存储单元的第一个字节的地址就是该变量的地址。
可以看出,变量a的地址是ffc3;变量b的地址是ffc1。内存中存储的都是2进制数据。
 
3.在调试过程中,我们采取打印的方式查看变量的地址:

int c = 10;

// 以16进制形式输出地址
printf("16进制:%x\n", &c); // 以10进制形式输出地址
printf("10进制:%d", &c);

输出结果:

一、一维数组

1.一维数组的定义

* 定义的形式为:类型  数组名[元素个数]

int a[5];

* []只能放在数组名的后面,下面的都是错误写法:

int[5] a; // 错误
int[] b; // 错误

* []里面的个数必须是一个固定值,可以是常量(比如6、8)、常量表达式(比如3+4、5*7)。绝对不能使用变量或者变量表达式来表示元素个数,大多数情况下不要省略元素个数(当数组作为函数的形参和数组初始化时除外)

下面的都是正确写法:

int  a[5];   // 整型常量
int b['A']; // 字符常量,其实就是65
int c[3*4]; // 整型常量表达式

下面的都是错误写法:

int a[]; // 没有指定元素个数,错误

int i = 9;
int a[i]; // 用变量做元素个数,错误

2.一维数组的存储

定义数组时,系统将按照数组类型和个数分配一段连续的存储空间来存储数组元素,如int a[3]占据了连续的6字节存储空间(在16位编译器环境下,一个int类型占用2个字节)。要注意的是,数组名代表着整个数组的地址,也就是数组的起始地址。

注意:其实a不算是变量,是个常量,它代表着数组的地址。上图把a放到变量一栏是为了方便大家理解数组结构。

数组a的地址是ffc1,a[0]的地址是ffc1,a[1]的地址是ffc3,a[2]的地址是ffc5。因此a == &a[0],即第一个元素的地址就是整个数组的地址

3.一维数组的初始化

* 初始化的一般形式是:类型  数组名[元素个数] = {元素1, 元素2, ...};

int a[2] = {8, 10};

其实相当于:

int a[2];
a[0] = 8;
a[1] = 10;
注意的是:C语言中编译器是不会对数组下标越界进行检查的,所以自己访问数组元素时要小心
 
 
* 元素值列表可以是数组所有元素的初值,也可以是前面部分元素的初值
int a[4] = {2, 5};

当数组为整型时,初始化未确定初值的元素,默认为0,所以上面的a[2]、a[3]都为0

* 当对全部数组元素都赋初值时,可以省略元素个数

int a[] = {2, 5, 7};

说明数组a的元素个数是3

* 数组初始化时的赋值方式只能用于数组的定义,定义之后只能一个元素一个元素地赋值

下面的写法是错误的:

1 int a[3];
2 a[3] = {1, 2, 3}; // 错误
3 a = {1, 2, 3}; // 错误

其实为什么是错误的写法呢?我们可以简要分析一下。

1> 第2行的a[3]代表着访问数组的第4个元素,首先这里已经是数组下标越界了;就算没有越界,给a[3]赋值时也应该赋一个int类型的整数,不应该是{}。

2> 第3行的a是数组名,代表着数组的地址,它是个常量!给常量赋值,那肯定错了!

4.一维数组与函数参数

如果忘记了实参和形参的意思,可以回看下《四、函数》这篇文章

* 一维数组的元素作为函数实参,与同类型的简单变量作为实参一样,是单向的值传递,即数组元素的值传给形参,形参的改变不影响实参

// b是test函数的形参(形式参数)
void test(int b) {
b = 9;
} int main()
{
int a[3];
a[0] = 10; printf("函数调用前的a[0]:%d\n", a[0]); test(a[0]); // a[0]是test函数的实参(实际参数) printf("函数调用后的a[0]:%d", a[0]);
return 0;
}

输出结果:

* 大家都知道,数组名代表着整个数组的地址,如果一维数组的名字作为函数实参,传递的是整个数组,即形参数组和实参数组完全等同,是存放在同一存储空间的同一个数组。这样形参数组修改时,实参数组也同时被修改了。形参数组的元素个数可以省略。

// b是test函数的形参(形式参数)
void test(int b[]) { // 也可以写int b[3]
b[0] = 9;
} int main()
{
int a[3];
a[0] = 10; printf("函数调用前的a[0]:%d\n", a[0]); test(a); // a是test函数的实参(实际参数) printf("函数调用后的a[0]:%d", a[0]);
return 0;
}

输出结果:

二、二维数组

1.二维数组的定义

定义形式:类型  数组名[行数][列数]

int a[2][3]; // 共2行3列,6个元素

2.二维数组的存储

* C语言把二维数组当作是一维数组的集合,即二维数组是一个特殊的一维数组:它的元素是一维数组。例如int a[2][3]可以看作由一维数组a[0]和一维数组a[1]组成,这两个一维数组都包含了3个int类型的元素

* 二维数组的存放顺序是按行存放的,先存放第一行的元素,再存放第2行的元素。例如int a[2][3]的存放顺序是:a[0][0] → a[0][1] → a[0][2] → a[1][0] → a[1][1] → a[1][2]

* 再来看看在内存中的存储情况,例如int a[2][2]

(注意:a[0]、a[1]也是数组,是一维数组,而且a[0]、a[1]就是数组名,因此a[0]、a[1]就代表着这个一维数组的地址)

1> 数组a的地址是ffc1,数组a[0]的地址也是ffc1,即a = a[0];

2> 元素a[0][0]的地址是ffc1,所以数组a[0]的地址和元素a[0][0]的地址相同,即a[0] = &a[0][0];

3> 最终可以得出结论:a = a[0] = &a[0][0],以此类推,可以得出a[1] = &a[1][0]

3.二维数组的初始化

* 按行进行初始化

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

* 按存储顺序进行初始化(先存放第1行,再存放第2行)

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

* 对部分元素进行初始化

int a[2][3] = { {2}, {3, 4} };
int b[3][3] = { { }, { , , 2}, {1, 2, 3}};

* 如果只初始化了部分元素,可以省略行数,但是不可以省略列数

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

有些人可能想不明白,为什么可以省略行数,但不可以省略列数。也有人可能会问,可不可以只指定行数,但是省略列数?

其实这个问题很简单,如果我们这样写:

int a[2][] = {1, 2, 3, 4, 5, 6}; // 错误写法

大家都知道,二维数组会先存放第1行的元素,由于不确定列数,也就是不确定第1行要存放多少个元素,所以这里会产生很多种情况,可能1、2是属于第1行的,也可能1、2、3、4是第一行的,甚至1、2、3、4、5、6全部都是属于第1行的

三维乃至更多维的数组就不再提及了,大家以此类推。

【C语言】08-数组的更多相关文章

  1. 【算法】C语言实现数组的动态分配

    C语言实现数组的动态分配 作者:白宁超 2016年10月27日20:13:13 摘要:数据结构和算法对于编程的意义不言而喻,具有指导意义的.无论从事算法优化方向研究,还是大数据处理,亦或者网站开发AP ...

  2. C语言一维数组、二维数组、结构体的初始化

    C语言数组的初始化表示方法 一.C语言一维数组初始化: (1)在定义数组时对数组元素赋以初值.如: static int a[10]={0,1,2,3,4,5,6,7,8,9}; 经过上面的定义和初始 ...

  3. go语言的 数组、slice、map使用(转)

    golang群 点击加入 go语言的 数组.slice.map使用, 由于网上有很好的说明, 不需要再写了,请看这几篇: Go语言中的 Array, Slice和 Map 深入学习golang五篇,以 ...

  4. go语言 类型:数组

    在go语言中数组array是一组特定长度的有序的元素集合. go的数组类型由两部分组成——类型和长度,二者缺一不可.数组本来就是一块存储相同类型元素的连续内存空间,因此决定一个数组的类型,必然需要决定 ...

  5. C语言基础--数组及相关

    概念: 一堆相同类型的数据的有序集合 格式: 元素类型  数组名称[ 元素个数 ] 定义数组: // 定义了一个名称叫做scores的数组, 数组中可以存放3个int类型的数据 ]; // 只要定义一 ...

  6. 学习C语言的数组

    C语言的数组 数组声明的实例:int num[3];只要记下这个模板就好. 不建议使用变量定义数组,如果使用了变量定义数组,作为数组的元素的个数,不初始化的情况下是随机值,如果初始化会直接报错 注意: ...

  7. 对于C语言中数组名是指针的理解

    我们都知道,c语言中数组名是一个指针,比如下面这段代码 #include<iostream>using namespace std;int main(){ int a[4]={1,2,3, ...

  8. c语言中数组相关问题

    c语言中数组相关问题: 1.数组基本定义: 相同数据类型的元素按一定顺序排列的集合,就是把有限个类型相同的变量用一个名字命名,然后用编号区分他们的变量的集合,这个名字称为数组名,编号称为下标.组成数组 ...

  9. 线性表之顺序存储结构(C语言动态数组实现)

    线性表的定义:N个数据元素的有限序列 线性表从存储结构上分为:顺序存储结构(数组)和 链式存储结构(链表) 顺序存储结构:是用一段连续的内存空间存储表中的数据 L=(a1,a2,a3....an) 链 ...

  10. C语言入门(16)——C语言的数组

    和结构体类似,数组也是一种复合数据类型,它由一系列相同类型的元素组成.C语言支持一维数组和多维数组.如果一个数组的所有元素都不是数组,那么该数组称为一维数组. 一维数组的定义方式 在C语言中使用数组必 ...

随机推荐

  1. eclipse 启动后,啥也不干,就一直在loading descriptor for XXX (XXX为工程名),,其他什么操作都不能操作。 如下图所示,保存文件也无法保存。 这个怎么办?一年好几天,什么都干不了!!!!!

    解决办法: 解决办法是 断一下网就好了

  2. 【转】仿百度输入框智能提示的js代码

    转自:http://www.jb51.net/article/40783.htm 对于我这个JS菜鸟,能找到这样的实属不容易啊!!! 刚开始老大让做这个功能,真是一点头绪都没有,万分感谢!!! 最近客 ...

  3. for循环,pydev提示未使用的变量,解决办法

    对于如下代码,pvdev会产生未使用变量的警告 for i in range(5): func() 解决办法: 把变量替换成下划线_,就不会生产告警了.改变后如下: for _ in range(5) ...

  4. ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(二) 实现聊天室连接

    上一篇已经简单介绍了layim WebUI即时通讯组件和获取数据的后台方法.现在要讨论的是SingalR的内容,之前都是直接贴代码.那么在贴代码之前先分析一下业务模型,顺便简单讲一下SingalR里的 ...

  5. stm32学习笔记——外部中断的使用

    stm32学习笔记——外部中断的使用 基本概念 stm32中,每一个GPIO都可以触发一个外部中断,但是,GPIO的中断是以组为一个单位的,同组间的外部中断同一时间只能使用一个.比如说,PA0,PB0 ...

  6. Android之记住密码与自动登陆实现

    本文主要讲述了利用sharedpreference实现记住密码与自动登陆功能 根据checkbox的状态存储用户名与密码 将结果保存在自定义的application中,成为全局变量 布局文件 < ...

  7. ytu 1998:C语言实验——删除指定字符(水题)

    C语言实验——删除指定字符 Time Limit: 1 Sec  Memory Limit: 64 MBSubmit: 327  Solved: 211[Submit][Status][Web Boa ...

  8. ORA-00824:cannot set SGA_TARGET or MEMORY_TARGET due to existing internal settings

    练习时执行一条修改数据库连接数的语句: alter system set processes=1 scope=spfile; 然后关闭数据库: shutdown 再启动数据库时,出现异常,报错信息如下 ...

  9. Ps 之路 更改前景色

     用快速选中工具 选中要改变的图片,选中你喜欢的颜色,按Alt+Del

  10. google地图引入网页

    <script src=);//指定坐标,缩放级别,setcenter 设置地图中心位置             //var mapControl = new GMapTypeControl() ...