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;
}
注意判断