博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言基础---5.数组相关详解:入门(一维数组 & 二维数组 & 应用案例)
阅读量:2394 次
发布时间:2019-05-10

本文共 6290 字,大约阅读时间需要 20 分钟。

文章目录

1.数组基础

在程序设计中,为了方便处理数据把具有相同类型的若干变量按有序形式组织起来——称为数组。

数组就是在内存中连续的相同类型的变量空间。同一个数组所有的成员都是相同的数据类型,同时所有的成员在内存中的地址是连续的。

在这里插入图片描述

2.数组的定义及赋值

#include 
int main(){
int a[10]; //定义了一个数组,名字叫a,有10个成员,每个成员都是int类型 a[0] = 0; //a[0]…… a[9],没有a[10] //…… //没有a这个变量,a是数组的名字,但不是变量名,它是常量 a[9] = 9; int i = 0; for (i = 0; i < 10; i++) {
a[i] = i; //给数组赋值 } for (i = 0; i < 10; i++) //遍历数组,并输出每个成员的值 {
printf("%d ", a[i]); } printf("\n"); return 0;}

3.一维数组的初始化

  • 在定义数组的同时进行赋值,称为初始化。
  • 全局数组若不初始化,编译器将其初始化为零。
  • 局部数组若不初始化,内容为随机值。
int a[10] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//定义一个数组,同时初始化所有成员变量int a[10] = {
1, 2, 3 };//初始化前三个成员,后面所有元素都设置为0int a[10] = {
0 };//所有的成员都设置为0int a[] = {
1, 2, 3, 4, 5 };//定义了一个数组,有5个成员 ,[]中不定义元素个数,定义时必须初始化

4.数组名:第一个元素的地址

#include 
int main(){
int a[10] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; //定义一个数组,同时初始化所有成员变量 printf("a = %p\n", a); printf("&a[0] = %p\n", &a[0]); int n = sizeof(a); //数组占用内存的大小,10个int类型,10 * 4 = 40 int n0 = sizeof(a[0]); //数组第0个元素占用内存大小,第0个元素为int,4 int i = 0; for (i = 0; i < sizeof(a) / sizeof(a[0]); i++) {
printf("%d ", a[i]); } printf("\n"); return 0;}
a = 00EFFE98			// 可以看到,数组名即为第一个元素的地址&a[0] = 00EFFE981 2 3 4 5 6 7 8 9 10

5.二维数组的定义及使用

1.基础定义

类型说明符 数组名 [常量表达式1] [常量表达式2]

  • int a[3][4]-------定义了一个三行四列的数组,数组名为a, 其元素类型为整型,该数组的元素个数为3×4个

在这里插入图片描述

  • 内存中不存在真正的二维数组,二维数组只是个抽象的概念。实际是多个一维数组的拼接,即放完一行之后顺次放入第二行,和一维数组存放方式是一样的。
  • 通过每行的首元素(例如,a[0] 和 a[1])可以找到每行的元素,然后再找到这行中的具体每个元素。

在这里插入图片描述

1.二维数组a[3][4],可以看做是数组的数组,即:最外层的一维数组,元素是a[0],a[1],a[2]

2.内存的一维数组a[0],a[1],a[2],对应的元素为a[0][0],a[1][0],a[2][0]…
3.中间层,a[0],a[1],a[2],即是外层数组的元素,也是内存数组的数组名
4. **a最终才能取到元素的值,就是因为2层数组的缘故(二维数组名栏目里面,有详细介绍)

#include 
int main(){
//定义了一个二维数组,名字叫a //由3个一维数组组成,这个一维数组是int [4] //这3个一维数组的数组名分别为a[0],a[1],a[2] int a[3][4]; a[0][0] = 0; //…… a[2][3] = 11; //给数组每个元素赋值 int i = 0; int j = 0; int num = 0; for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
a[i][j] = num++; } } //遍历数组,并输出每个成员的值 for (i = 0; i < 3; i++) {
for (j = 0; j < 4; j++) {
printf("%d, ", a[i][j]); } printf("\n"); } return 0;}
0, 1, 2, 3,4, 5, 6, 7,8, 9, 10, 11,

2.二维数组的初始化

//分段赋值 	int a[3][4] = {
{ 1, 2, 3, 4 },{ 5, 6, 7, 8, },{ 9, 10, 11, 12 }}; int a[3][4] = {
{
1, 2, 3, 4 }, {
5, 6, 7, 8, }, {
9, 10, 11, 12 } }; //连续赋值 int a[3][4] = {
1, 2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12 };
//可以只给部分元素赋初值,未初始化则为0	int a[3][4] = {
1, 2, 3, 4 };// 结果为:// 1, 2, 3, 4,// 0, 0, 0, 0,// 0, 0, 0, 0,
//所有的成员都设置为0	int a[3][4] = {
0};// 结果为:// 0, 0, 0, 0,// 0, 0, 0, 0,// 0, 0, 0, 0,
//[]中不定义元素个数,定义时必须初始化	int a[][4] = {
1, 2, 3, 4, 5, 6, 7, 8};// 结果为:// 1, 2, 3, 4,// 5, 6, 7, 8,

3.二维数组名:

因为数组名是二维数组,2层嵌套,需要a才能取到最终的值:**

#include 
int main() {
int a[3][4] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; printf("a 的地址---%p\n", a); printf("*a的地址---%p\n", *a); printf("**a的值---%d\n", **a); return 0;}
a 的地址---005DFCC4*a的地址---005DFCC4**a的值---1
#include 
int main(){
//定义了一个二维数组,名字叫a //二维数组是本质上还是一维数组,此一维数组有3个元素 //每个元素又是一个一维数组int[4] int a[3][4] = {
1, 2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12 }; printf("a = %p\n", a); //数组名为数组首元素地址,二维数组的第0个元素为一维数组 printf("a[0] = %p\n", a[0]); //第0个一维数组的数组名为a[0] //测二维数组所占内存空间,有3个一维数组,每个一维数组的空间为4*4 //sizeof(a) = 3 * 4 * 4 = 48 printf("sizeof(a) = %d\n", sizeof(a)); printf("sizeof(a[0]) = %d\n", sizeof(a[0])); //测第0行一维数组所占内存空间,a[0]为第0个一维数组,大小为4,即:4*4=16 printf("sizeof(a[0][0]) = %d\n", sizeof(a[0][0])); //测第一个元素字节大小,即:第0行0列元素a[0][0],是一个int类型,4字节 printf("i = %d\n", sizeof(a) / sizeof(a[0])); //求二维数组行数 printf("j = %d\n", sizeof(a[0]) / sizeof(a[0][0])); // 求二维数组列数 printf("n = %d\n", sizeof(a) / sizeof(a[0][0])); //求二维数组行*列总数 return 0;}
a = 008FFE40a[0] = 008FFE40sizeof(a) = 48sizeof(a[0]) = 16sizeof(a[0][0]) = 4i = 3j = 4n = 12

4.二维数组应用案例:

#include 
int main(){
//二维数组: 五行、三列 //行代表人: 老大到老五 //列代表科目:语、数、外 float a[5][3] = {
{
80, 75, 56 }, {
59, 65, 71 }, {
59, 63, 70 }, {
85, 45, 90 }, {
76, 77, 45 } }; int i, j, person_low[3] = {
0 }; float s = 0, lesson_aver[3] = {
0 }; for (i = 0; i < 3; i++) {
for (j = 0; j < 5; j++) {
s = s + a[j][i]; if (a[j][i] < 60) {
person_low[i]++; } } lesson_aver[i] = s / 5; s = 0; } printf("各科的平均成绩:\n"); for (i = 0; i < 3; i++) {
printf("%.2f\n", lesson_aver[i]); } printf("各科不及格的人数:\n"); for (i = 0; i < 3; i++) {
printf("%d\n", person_low[i]); } return 0;}
各科的平均成绩:71.8065.0066.40各科不及格的人数:212

6.常见错误用法:

1.未初始化的局部变量数组 & 未初始化的全局变量数组

#include 
int a[5];int main() {
int b[5]; for (int i = 0; i < 5; i++) {
printf("a数组的各个元素-----%d\n", a[i]); } for (int i = 0; i < 5; i++) {
printf("b数组的各个元素-----%d\n", b[i]); }}
a数组的各个元素-----0a数组的各个元素-----0a数组的各个元素-----0a数组的各个元素-----0a数组的各个元素-----0b数组的各个元素------858993460b数组的各个元素------858993460b数组的各个元素------858993460b数组的各个元素------858993460b数组的各个元素------858993460
  • 未初始化的全局变量,系统默认给的值为0
  • 未初始化的局域变量,系统会随机分配值

2.二维数组初始化错误(使用小括号)

#include 
int main() {
int a[3][2] = {
(1, 2), (3, 4), (5, 6) }; // {2,4,6} 或 {2,4}{6,0},{0,0} int* p; p = a[0]; printf("%d %d\n", a[0][0],p[0]); //p[0]代表的是第0行的首元素吗? printf("%d %d\n", a[1][0],p[1]); //p[1]代表的是第1行的首元素吗? printf("%d %d\n", a[2][0],p[2]); printf("===============\n"); printf("%d \n", a[0][1]); printf("%d \n", a[1][1]); printf("%d \n", a[2][1]); return 0;}
2   26   4		// 这里为什么不一样??0   6===============400

二维数组是一个抽象的概念,存储的值转换为抽象的概念如下:

二维数组初始化的时候,int a[3][2] = { (1, 2), (3, 4), (5, 6) },这个相当于是 int a[3][2] = {2, 4, 6}

int a[3][2] = {
2, 4, 6} // 原始二维数组int a[3][2] ={
{
2, 4},{
6,0}, {
0,0} } // 转换之后的二维数组
a[0][0]    = 2a[1][0]	   = 6a[2][0]    = 0a[0][1]    = 4a[1][1]	   = 0a[2][1]    = 0

指针和地址,对应实际内存的地址,某个地址存储什么值,直接就读取什么值:

根据如上代码,我大致推测的存储方式:

在这里插入图片描述

  • int a[3][2] = {2, 4, 6}二维数组,内存存储的时候,可以把真个二维数组看成是一个一维数组
  • 上图中,每个数值占用4个字节,所以可以把2,4、6,看作是一个正常的连续存储的一维数组
  • 因为指针p指向了首地址,所以可以把p看做是数组名去获取值,或通过指针偏移获取值,如:*(p+i)

为了证明我们的推测,再次准备代码:

#include 
int main() {
int a[3][2] = {
2, 4, 6, 8, 9 }; int* p; p = a[0]; printf("%d %d \n", p[0], *(p + 0)); printf("%d %d \n", p[1], *(p + 1)); printf("%d %d \n", p[2], *(p + 2)); printf("%d %d \n", p[3], *(p + 3)); printf("%d %d \n", p[4], *(p + 4));}
2   24   46   68   89   9

最终发现,通过偏移量或者p[i]这两种形式,都可以正常获取值了。

转载地址:http://wveab.baihongyu.com/

你可能感兴趣的文章
Linux下apache+svn+ssl完美结合搭建安全版本控制平台
查看>>
Nginx 0.8.35 Space Character Remote Source Disclosure
查看>>
showrun的cissp经验谈
查看>>
6月4日要买的书
查看>>
nginx Remote Source Code Disclosure and Denial of Service Vulnerabilities
查看>>
Anti-sec安全培训 部分试看视频
查看>>
FreeBSD kernel NFS client local vulnerabilities
查看>>
JXplorer 的简单使用
查看>>
如何启用 LDAP 签名 Windows Server 2008 中
查看>>
获取ngnix,apache,php,mysql的编译参数 zz from xi4oyu
查看>>
使用ettercap嗅探ssh口令
查看>>
OTPs: Using s/Key with SSH via OPIE
查看>>
使用arpwatch和arping来排查ARP攻击
查看>>
Linux硬件监控方法
查看>>
RSA SecurID Authentication linux sshd PAM deploy
查看>>
转: pam 禁止某些用户使用ssh 远程登录
查看>>
小包优先+web优先+游戏爆发+单IP限速+连接数限制 脚本V2.0
查看>>
Rhel5 配置NTP服务
查看>>
ZZ Quick-Tip: Linux NAT in Four Steps using iptables
查看>>
北京的住房公积金是否可用于还外地的房贷
查看>>