指针
1.1 概念:一个变量的地址就是指针。
前提:任何一个变量都需要存储在计算机的内存中,编译器会为计算机内存的每个字节都进行顺序编号,每个字节的编号是唯一的,这样就方便计算机根据编号找到对应的存储位置。我们将这些编号称为某个字节的地址。
1.2 变量名
当利用C语言声明了一个变量时,计算机编译器会根据变量的数据类型,在内存空间中开辟一个对应的一段内存。编译器会将这段内存和这个变量进行“匹配”,这样,开发者就可以利用变量名来访问这段内存空间了。这种方式被称为“直接访问”。
1.3 变量的地址
当一个变量被声明后,编译器就将这个变量空间中的第一个字节的编号和变量名进行“捆绑”,当程序员利用变量名来实现对于变量访问时,实际上是通过变量名和变量的第一个字节的地址实现的对应关系来访问到的。我们将这种通过实际上地址访问计算机的过程称为“寻址”。
1.4 指针变量
1.4.1 直接寻址和间接寻址
直接寻址:通过变量名直接访问到内存空间的过程称为直接寻址
间接寻址:通过指针变量间接访问到对应变量的内存空间的过程称为间接寻址
1.4.2 概念:
指针类型:C语言的一种数据类型,用于保存变量的内存地址的一种数据类型,并且可以通过这种类型的变量间接的访问到对应的存储空间。
变量的内存地址:该变量的第一个字节的内存地址,在32位编译器下,内存中一个字节的地址是32位的。意味着内存地址的取值范围:0x0000 0000 ~ 0xFFFF FFFF(4GB),说明当一个变量存取值的时候都需要找到该变量的内存地址来进行操作。
我们可以使用&变量名的方式来获取一个变量的地址
1.5 指针变量
概念:指针类型的变量,用于保存一个变量的内存地址,并且可以通过这个地址进行特殊的计算,找到对应变量的存储空间
我们现在常说的指针实际上就是指针变量
语法格式:
① 声明
基类型* 指针变量名;
② 初始化
基类型* 指针变量名 = &值;
③ 赋值
指针变量名 = &值;
1.6 指向变量的指针变量
如果一个指针变量保存了指定的变量的内存地址,我们就称这个指针变量指向了那个变量。
1.7 指针变量的基类型
一个指针变量的基类型代表这个指针变量应该指向的那个变量的数据类型。但是指针变量可以保存任意类型的变量的地址,因此单纯从保存地址来说,基类型没有意义。区别在于利用指针变量间接访问指向的那块内存空间的过程。
1.8 指针变量的计算
语法:
* 指针变量名;
目的是利用指针变量名找到指向的那块内存空间。此时* 指针变量名就等于变量本身
计算过程:
① 将指针变量中的地址,当做要访问到的地址
② 将指针变量的基类型当做要访问的空间的数据类型
③ 将指针变量的基类型的大小作为偏移量
④ 将这个空间进行访问
为了避免指针变量在间接访问变量时出错,所以指针变量的基类型应该和指向的变量的类型一致
对于普通变量,和指针变量而言,* 和& 互为逆运算
int main()
{
int* p;
char* pc;
printf("%d %d\n", sizeof(p), sizeof(pc));
int x = 300;
p = &x;
pc = &x;
printf("%p %p\n", p, pc);
printf("%d %d\n", *p,*pc);
*&x;
&*p;
return 0;
}
1.9 野指针
声明一个指针变量但是没有初始化,意味着该指针变量的指向是随机的,此时直接使用指针变量来访问对应的内存地址,会产生不可预料的错误,我们称这种未被初始化的指针变量为“野指针”。为了防止这种现象产生,在指针初始化时,建议将该指针变量置为空
基类型* 指针变量名=NULL;
此时,该指针变量被称为空指针,不指向任何有效变量。
/*p指针变量在栈空间开辟,在栈空间
上的变量未被赋值或初始化时,其值是
随机值
*/
//int* p;//野指针
//*p=100;//访问会出错
//int* p = NULL;//空指针,不指向任何一个变量
//printf("%p\n", p);
int a = 88;
int* p = &a;
printf("%p %p\n", &a, p);
printf("%p\n", p - 1);