一、多维数组和指针
从二维数组的角度看,x代表的是二维数组首元素的地址,现在的首元素不是一个简单的整型元素,而是由四个整型元素所组成的一维数x代表的是首行(即第0行)的首地址。x+1代表第1行的首地址。
x[0]、x[1]、x[2]、x[3]、x[4]、x[5]既然是一维数组名,而C语言由规定了数组名代表数组首元素地址,因此x[0]代表一维数组x[0]中第0列元素的地址,即&x[0][0]。x[1]的值是&x[1][0],以此类推。
请考虑0行1列的元素的地址怎么表示?x[0]为一维数组名,该移位数组中序号为1的元素的地址显然应该用x[0]+1来表示。此时 x[0]+1 中的1代表1个列元素的字节数,即4个字节。今x[0]的值是2000,x[0]+1的值是2004(而不是2016),这是因为现在是在一维数组范围内讨论问题的,正如有一个一维数组a。a[0]+1是其第一个元素x[1]一样。x[0]+0、x[0]+1、x[0]+2、x[0]+3、x[0]+4、x[0]+5分别是x[0][0]、x[0][1]、x[0]2]、x[0][3]、x[0][4]、x[0][5]的地址。
x[0]和*(x+0)等价,x[1]和*(x+1)等价,x[i]和*(x+i)等价。因此,x[0]+1和*(x+0)+1都是&x[0][1]。x[1]+2和 *(x+1)+2的值都是&x[1][2]。
进一步分析,欲得到x[0][1]的值,用地址法怎么表示呢?既然x[0]+1和*(x+0)+1是x[0][1]的地址,那么,*(x[0]+1)就是x[0][1]的地址。同理,*(*(x+0)+1)或*(*x+1)也是x[0][1]的值。
二、字节对齐
https://blog.csdn.net/cclethe/article/details/79659590
三、静态库和动态库
四、内存泄漏和内存泄漏
内存溢出,申请不到足够的内存;
内存泄露,无法释放已申请的内存;
两者关系:内存泄露 → 剩余内存不足 → 后续申请不到足够内存 →内存溢出。
五、const
- 1、什么是const?
const就是constant的缩写,意思是“恒定不变的”,它是定义只读变量的关键字,或者说const是定义常变量的关键字,常类型的变量或对象的值是不能被更新的
- 2、为什么引入const?
const推出的初始目的,就是为了取代预编译指令,消除它的缺点,同时继承它的优点
1. define只是用来进行单纯的文本替换,define常量的声明周期止于编译期,不分配内存空间,它存在于程序的代码段,在实际程序中它只是一个常数,一个命令中的参数并没有实际的存在;而const常量存在于长须的数据段,并在堆栈中分配了空间,const常量在程序中确实存在,且可以被调用、传递
2. const常量有数据类型,而define常量没有数据类型,编译器可以对const常量进行类型安全检查,但是define不行
3.很多IDE支持调试const定义的常量,而不支持define定义的常量
综上
由于const修饰的变量可以排除程序之间的不安全性因素,保护程序中的常量不被修改,而且对数据类型也会进行相应的检查,极大地提高了程序的健壮性,所以一般更加倾向于用const定义常量类型
- 3、const有什么主要的作用?
(1)可以定义const常量,具有不可变性。例如:const int MAX = 100; int array[MAX];
(2)便于进行类型检查,使编译器对处理内容有更多了解,以消除一些隐患
例如:void f(const int i) {......}编译器就会知道 i 是一个常量,不允许修改。
(3)可以保护被修饰的东西,防止意外的修改,增强程序的健壮性。还是上面例子,如果在函数体内修改了 i ,编译器就会报错
例如:void f(const int i){ i = 1001;} error!
(4)为函数重载提供了一个参考
class A { void f(int i) { ...... } //一个函数 void f(int i) const { ...... } //上一个函数的重载..... };
(5)提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。
- 4、const的使用
const在实际中用得并不多,先列出如下const短小总结,const关键字修饰指针,const在*号的左边还是右边(左定值,右定向)
1.const int a; //a是一个常整形数 2.int const a; //a是一个常整形数 3.const int *a; //a是一个指向常整数型的指针(整形数是不可修改的,但指针可以) 4.int const *a; //a是一个指向常整数型的指针(同上) 5.int *const a; //a是一个指向整形数的常指针(指针保存内容不可修改) 6.int const * const a; //a是一个指向常整形数的常指针(指针指向的整形数是不可修改的,同时指针也是不可修改的)
(1)int const * ;
int const *a 和 const int *a意义一样。
从右往左看,进行解析,这个a是一个指针,而且是一个常量,类型是整形,称为指针常量
特点:*a指向一个整形的常量,但是不能通过修改p所指向内存单元的值,只能通过修改其所指向的对象,可称为指向常整形的指针
int data = 88; const int number = 99; const int *p1 = &number; p1 = &data; //允许通过编译,允许修改所指向的对象 *p1 = 10086; //不允许通过编译,无法通过指针修改内容
(2)int * const a;
从右往左看,一个常量a被定义为整形指针。可称为指向整形的常指针
特点:常量a是一个整型类型的指针,它能通过指针来进行修改其中的内容,但当它已经指向一个地址之后,便不能再指向其他地址,和int const*有区别
int data = 88; int k = 99; int * const p2 = &data; *p2 = 10010; //允许通过编译,允许通过指针修改内容; p2 = &k; //不允许通过编译,无法修改所指向的对象; (3)const int * const p;
从右往左看,结合上面两个,可以看做常量指针常量,即常量p是一个整形的指针,而且这个指针还是个常量
int data = 88; int k = 99; int const * const p3 = &data; p3 = &k; //不允许通过编译 *p3 = 4399; //不允许通过编译