笔记:数组

1 数组:
1.1.数组只能在定义的时候赋予初值

//正确例子
int arryA[6] = {1, 2, 3, 4, 5, 6};
int arryB[2][3] = {{1, 2, 3}, {4, 5, 6}};
int GetValue();
int nValue = 5;
int arryC[6] = {1, GetValue(), 3, 4, nValue++, 6};
//错误例子:int arry[6] = {, , , 4, 5, 6}; 

1.2.数组赋予初值,如果赋值的数据个数,小于数组大小,其余默认赋予0值
(语法规定,与编译器无关)

int arry[6] = {1};//其余5个数组元素分别被赋予0值

1.3 数组的寻址行为,编译器行为

int arry[6] = {1, 2, 3, 4, 5, 6};
/*
数组访问的寻址公式如下:
arryA[n] 的地址 = ary + sizeof(int) * n;
arryB[n][m] 的地址 = (arryB+ sizeof(int(3)) * n) + sizeof(int) * m;
                  = (arryB+ sizeof(int) * 3 * n) + sizeof(int) * m;
                  = arryB+ sizeof(int) * (3*n + m);
*/
/*
如何用数组访问到内存地址中的数据
arryA[n] 的地址 = ary + sizeof(int) * n;
0x0040003C = ary + sizeof(int) * n;
(0x0040003C - ary) / sizeof(int) = n;
*/

int arryA[6] = {1, 2, 3, 4, 5, 6};
n = (0x0040003C - (int)arryA) / sizeof(int);
printf("%08x", arryA[n])
int* ptr = NULL;
printf("%08x", &ptr[6]);//打印结果应该是00000018(因为6*4=24,十六进制为18)

1.4 数组名的含义:
1.4.1 表示数组首地址
1.4.2 表示常量:(当其不作为函数参数使用时)
1.4.3 表变量:作为函数参数使用

int arryA[6] = {1, 2, 3, 4, 5, 6};
arryA++;//编译立马报错,因为arryA是一个常量
/*
其中 arryA视为常量,
延伸:常见的常量例子:"abcd" , 123 
其他:四则运算,逻辑运算,位运算,关系类的运算最终得到的结果都是常量
     赋值类运算得到的结果是左值,左值是什么类型,结果就是什么类型
*/
Fun(int arryB[], int nLen)
{
  arryB++;//这里是正确的,因为arryB作为函数参数使用,本身是一个变量
}

2 概念厘清:
内存空间是线性的:表示唯一前驱唯一后继,但不一定连续,是一种逻辑描述
连续:一遍描述的物理关系
编译:产生机器代码,或者中间码(Java)
链接:平台相关,生成限于某类平台使用的程序

3.编译行为例子
n*3 +n*5 可以编译优化为 n*8
3/n + 5/n 不可以编译优化为 8/n (注意除法是整除运算与数学不完全等价)

4.关于递归编程中栈溢出,运行时候报错的代码一般是0xC00000F0
如果在常规递归编程中,程序逻辑完全正确,但是栈不够用,可以考虑在VC++环境中设置栈大小
栈大小设置截图

5.strlen() 和 sizeof()
strlen是一个函数。
sizeof是运算符,在c++语法中可以重载。

char str1[64] = "abcdefg";
char str2[64] = {'\0'};
int nLen1 = sizeof(str1); //nLen1 == 64
int nLen2 = sizeof(str2); //nLen1 == 64
int nSLen1 = strlen(str1);//nSLen1 == 7
int nSLen2 = strlen(str2);//nSLen1 == 0

6.关于scanf()获取输入时候匹配的数据类型

int nValue1 = 0;
short int nValue2 = 0;
long int nValue3 = 0;
scanf("%d", &nValue1);
scanf("%hd", &nValue2);
scanf("%ld", &nValue3);

7.32位计算机中内存地址管理:内存地址采用模4进行管理
这里写图片描述
如图所示:要取红框内的四个字节内容
在模4地址下,如果使用int 数组寻址,并去内容来获取红框的数据0xFFE0B1F1

int nAry[8] = {1,2,3,4,5,6,7,8};
int nValue1 = nAry[(0x0012ffac - nAry) / sizeof(int)];
int nValue2 = nAry[(0x0012ffb0 - nAry) / sizeof(int)];
int nRed = nValue1 >>16 + nValue2 << 16;

8.程序入口点地址查找

int main(int argc, char* argv[])
{
  short int nArry[8] = {0};
  //0x00400000 = nArry + sizeof(int)*n
  unsigned int n = (0x00400000 - (int)nArry) / sizeof(short int);  
  printf("0x00400000:%p\r\n",  nArry[n]);
  if(nArry[n] != 'ZM')// 0x5A4D 5A-'Z', 4D-'M'
  {
    return 0;
  }

  //0x0040003C = nArry + sizeof(int)*n
  unsigned int m = (0x0040003C - (int)nArry) / sizeof(short int);  
  printf("0x0040003C:%p\r\n",  nArry[m]);

  //0x0040003C位置取内容 + 0x00400000
  unsigned int k = (0x00400000 + nArry[m] - (int)nArry) / sizeof(short int);  
  printf("*(0x0040003C)+ 0x00400000:%p\r\n",  nArry[k]);
  if(nArry[k] != 'EP')// 0x4550 50-'P',45-'E'
  {
    return 0;
  }
  //程序入口点地址:nArry[k]的地址往高地址移动40个字节的位置取值+0x00400000
  printf("程序入口点地址:%p\r\n",  0x00400000 + nArry[k+20]);

system("pause");
return 0;
}

注意判断
这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值