C11- 数组

复习上一次学习的函数过程

  • 栈:局部变量,参数; 生长方向:由高到低;
  • 栈帧:只有一个出口;原则是:先进后出;当程序运行的时候,每个被调用的函数,在内存的栈都有一块对应的空间,成为栈帧
    作用:
    学习了栈帧保存的 返回地址与上一层栈帧信息 以后调试的时候 可以调用堆栈 看哪里传参过来的

数组定义与使用

为什么需要数组
对应某种同类型的存储 是分开储存的

int nValue1=520;
int nValue2=1314;
...

对于同类型的储存,以上方法是比较冗余的
所以发明了数组,去存储同类型的数据
简化以上操作

int Ary[]={520,1314,...};
int main(int argc, char argv[])
{
 int Arry[] = {100, 200, 3,5 };

 for (size_t i = 0; i < 4; i++)
 {
  printf("%d\r\n", Arry[i]);
}
 return 0;
}

这样就定义了5个int类型的数据

数组的引用(修改)

对特定的数值进行 修改

数组名+下标=修改的值

注意数组的下标是从0开始的

数组的初始化

int main(int argc, char argv[])
{
 int Arry[10] = {100, 200, 3,5 ,};

 for (size_t i = 0; i < sizeof(Arry)/sizeof(Arry[0]); i++)
 {
  printf("%d\r\n", Arry[i]);
}
 return 0;
}

对于没有明确给定的值,就会赋值为0

数组一旦初始化,没有机会进行数组的批量赋值

数组名是什么

数组名就是数组的首地址

int main(int argc, char argv[])
{
 int Arry[10] = {100, 200, 3,5 };
 printf("%p,%p", Arry, &Arry[0]);
 return 0;
}

sizeof运算符的作用

sizeof计算 数据类型或者变量大小
当sizeof的对象是数组名时候,是整个数组的大小

int main(int argc, char argv[])
{
 int Arry[3][3] = {
  1, 2, 3,
  3, 4, 5,
  6, 7, 8,
 };

 int Arry2[3] = {
  1,
  2,
  3,
 };
 printf("%d\r\n", sizeof(Arry));
 printf("%d\r\n", sizeof(Arry2));
 return 0;
}

Arry大小4x9=36;
Arry2大小3x4=12;

所以根据这个原理,可以计算数组的元素个数。

int ArySize=sizeof(Arry);//总的数组大小
int AryCount=sizeof(Arry[0]);// 单个数组大小
int AryItem=ArySize/AryCount;// 元素个数

数组的原理

数组的两个特点

  • 一致性:一个数组的所有元素的类型,都是一样的。
  • 连续性:所有的元素是连续排列的(内存)

但是数组是可以越界的
如果定义为3个元素
但是用第4个元素

char cArry[3]={0};
char c=cArry[4];

是不可未知的,随机地址
超过太多就会崩溃

数组的寻址公式

int main(int argc, char argv[])
{

 int Arry2[] = {
  1,
  2,
  3,
 };
 printf("%p\r\n", Arry2);//0019FF04
 printf("%p\r\n", &Arry2[0]);
 printf("%p\r\n", &Arry2[1]);
 printf("%p\r\n", &Arry2[2]);
 printf("%p\r\n", &Arry2[3]);
 printf("\r\n");
 printf("%p\r\n", &Arry2[-1]);
 printf("%p\r\n", &Arry2[-2]);
 printf("\r\n");
 printf("%p\r\n", &2[Arry2]);
 return 0;
}

对于 数组地址如果超过了数组的范围,还是会按规律去计算。
即使是负数 也是从首地址开始计算。
对于调换位置,其实对于寻址是不影响的
对于type以及小标为i的寻址计算

&nArry2[i]=nArry2+i*sizeof(type)

以上以上是数学意义,在C语言中,编译器其实已经帮助我们将i乘以了sizeof(type) 使得我们可以更方便的使用数组。
所以可以理解

&nArry[-2]=nArry + (-2)*sizeof(type);
&2[nArry]=nArry + (2)*sizeof(type);

数组作为参数传参的特点

当我们将数组当作参数传参的时候,传过去的是首地址 (地址占 4个字节)
不是数组的所有内容传过去

void MyFun(int Arry[])
{
 printf("%d\r\n", sizeof(Arry));
}

int main(int argc, char argv[])
{

 int Arry2[] = {
  1,
  2,
  3,
 };
 printf("%d\r\n", sizeof(Arry2));
 MyFun(Arry2);
 return 0;
}

对于传过去是地址所以可以进行,更改内容,地址是不变的,所以不会被当作局部变量释放掉

void MyFun(int Arry[])
{
 Arry[2] = 111;
 printf("%d\r\n", sizeof(Arry));
}

int main(int argc, char argv[])
{

 int Arry2[] = {
  1,
  2,
  3,
 };
 printf("%d\r\n", sizeof(Arry2));
 MyFun(Arry2);
 printf("%d\r\n", Arry2[2]);
 return 0;
}

二维数组

二维数组寻址公式

在这里插入图片描述

由上面图可以知道,行是可以自动计算的,但是列是不可以的;
由此可以推知 寻址公式与初始化的列数有关

int main(int argc, char argv[])
{
 int Arry3[][3] = {
  1, 2, 3,
  4, 5, 6,
  7, 8, 9,
 };
 for (size_t i = 0; i < 3; i++)
 {
  for (size_t j = 0; j < 3; j++)
  {
   printf("%d\t", Arry3[i][j]);
  }
  printf("\n");
 }
 return 0;
}

所以从以上 推理 可以得到公式
对于一个type类型的 M行 N列的数组寻址

&Ary[i][j]=Ary+(i*N+j)*sizeof(type);  //是与总列数有关,所以定义的时候 必须定义列数

其实二维数组是特殊的一维数组

int nArry[3];// int[3] nArry   
int nArry[2][3];//int [3] nArry[2]   
int main(int argc, char argv[])
{


 int Arry3[][3] = {
  1, 2, 3,
  4, 5, 6,
  7, 8, 9,
 };
 printf("%p\r\n", Arry3);
 printf("%p\r\n", &Arry3[0]);
 printf("%p\r\n", &Arry3[0][1]);
 printf("%p\r\n", &Arry3[0][2]);
 printf("%p\r\n", &Arry3[1][0]);
 return 0;
}

俄罗斯方块铺垫

在一个项目中都遵从MVC模式
工程模块划分的意识

  • Model 模型,数据
  • View UI 外观
  • Control 操作,即将数据和UI的桥梁
    我们现在 所做的Model view 数据不多所以分为
Model.h
Model.cpp
View.h
View.cpp

.h文件是申明
.cpp是实现代码
头文件的前面应该加入

#pragma once

全局变量的声明要放在头文件中 用关键字extern

extern char g_chBackGround[GAME_ROW][GAME_COL];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值