1、内存
1、内存是线性的,内存的线性是物理基础。
内存是以字节为单位进行编址的,内存中的每个字节都对应一个地址,通过地址才能找到每个字节。
2、变量的地址:变量对应内存中的一段存储空间,用这段存储空间的第一个字节的地址表示变量
的地址,即低位字节的地址。
可通过Reference(&)引用获得变量的地址。dereference (*) 解引用
3、地址的大小:32位机的情况下,无论是什么类型大小均是 4。而 64位机大小均是 8。
2、指针常量
1、指针是有类型的地址。(int *)0x1ea4d511
2、指针的类型,决定了,该指针的寻址能力。即从指针所代表的地址处的寻址范围。
3、指针变量
1、定义: type * variable;
* 表示该变量是一个指针变量。
type 表示该变量的内存存放的地址的寻址能力。
2、如果直接赋给指针变量一个地址,对其访问是很危险 的。因为,我们不知道此址处是否一块什么区域 ,有可能是一段内核区域 ,访问很可能会 导致系统崩溃 。
3、指向谁,就保存了谁的地址。
4、野指针: 一个指针变量,如果,指向一段无效的空间,则该指针称为野指针。
常见情型:①未初始化的指针;②指向已经被释放的空间。
对野指针的读或写崩溃尚可忍受,对野指针的写入成功,造成的后果是不可估量的。
5、NULL指针:NULL是一个宏,俗称空指针,他等价于指针 (void*)0
define NULL ((void *)0)
6、void本质:void即无类型,可以赋给任意类型的指针,本质即代表内存的最小单位,在 32位机上地位等同于 char。
7、指针的运算:指针的算术运算,不是简单的数值运算,而是一种数值加类型 运算。将指针加上或者减去某个整数值(以 n*sizeof(T)为单位进行操作的)。
注意:①只有当指针指向一串连续的存储 单元时,指针的移动 才有意义。才可以将一个指针变量与一个整数 n做加减运算。
②指针的运算只能发生在同类型或整型之间,否则会报错或是警告。
③指针的运算,除了数值以外,还有类型在里面。
4、一维数组与指针
一维数组名对应一级指针:数组除了可以用下标法和本质法访问以外,还可以用指针法访问。能用数组名解决的问题的,都可以用指针来解决,而能用指针来解决的问题,并一定能用数组名来解决。
总结:int a[10] = {0};
int * p = a;
①数组名是一个常量,不允许重新赋值。
②指针变量是一个变量,可以重新赋值。
③p+i和 a+i均表示数组元素 a[i]的地址,均指向 a[i]
④*(p+i)和 *(a+i)均表示 p+i和 a+i所指对象的内容 a[i]。
⑤*p++:等价于 *(p++)。其作用:先得到 *p,再使 p=p+1。
⑥(*p)++:表示将 p所指向的变量(元素)的值加 1。即等价于 a[i]++ 。
⑦指向数组元素的指针也可以表示成数组的形式,即允许指针变量带下标,如*(p+i)可以表示成 p[i]。
5、二维数组与数组指针
从a到a[0]到a[0][0]经历了什么?
小结:
①a是数组首元素的地址,所以 a的值和 &a[0]的值相同,
另一方面, a[0]本身是包含 4个整数的数组,因此, a[0]的值同其首元素的地址 &a[0][0]相同。
简单的讲, a[0]是一个整数大小对象的地址,而 a是 4个整数大小对象的地址。
因为整数和 4个整数组成的数组开始于同一个地址,因此 a和 a[0]的值是相同的。
②a所指的对象大小是 4个 int,而 a[0]所指的对象大小一个 int,
因此, a+1 和a[0]+1的结果是不同的。
学习资料: 《零基础入门C语言--王桂林》