前言
指针,是我们在学习C语言中的一个重难点,关乎到我们学习C语言的深度和理解,所以,想要学好C语言,在学习C语言的时候就一定要将指针学懂学透。下面是我对C语言的粗糙理解,如果可以帮到大家那是最好不过了,要是有什么不对地方,也希望大家可以提醒我一句。
指针
指针是什么
指针是内存中的地址,是内存中的各个数据的门牌号。
大家可以将计算机类比成我们的现实世界,我们的世界是被分为一个一个空间的,我们就生活在一个一个的空间里面,每个空间都会有独立的编号或者名称(这就像我们点外卖的时候我们会有一个地址,可以让外卖小哥将外卖准确无误地将外卖送到我们手里)。
在内存中也是,对于各个数据,我们都有一块相对独立的空间来存放,对于每个数据,都会有一片独立的空间来存储。这时也就会有一个对应的编号来指向这块空间,这个编号也就叫做地址,而指针就是专门用来存放这个地址的。
指针的大小
指针变量指针变量,只要是变量,就应该需要内存来存储它,而指针在内存中存储需要占用多少个字节呢?对于其他数据类型,指针有点不一样的地方,其他数据类型都有明确的大小,并且在任何环境下都不会改变。而指针需要看是在什么环境下运行的。
- 在32位的机器下,指针是占用4个字节的。
- 在64位的机器下,指针是占用8个字节的。
指针的定义和赋值
指针在定义的时候需要声明指向的数据的类型,这也决定了这个指针的步长(在进行±运算或者读取的时候需要±或者读取多少个字节)。 这就像数组一样,我们需要在定义数组的时候定义好长度和元素个数。
int num = 9;
int* ptr_num = # //int类型的指针指向int类型的变量的地址
char ch = 'A';
char* ptr_ch = &ch; //char类型的指针指向char类型的变量的地址
在给指针赋值的时候,需要注意要不要带上取地址符号&,因为指针内部存储的是地址。需要注意的是,如果是存储数组的地址的时候,就不需要带上&符号了,因为数组名本身就是数组的首地址。因为在 &数组名 就是整个数组的地址了,这样进行± 运算的时候就是±整个数组的长度了。像这样的情况还有一个 sizeof(数组名),这样出现计算出来的也会是整个数组的长度。
指针的使用
在使用指针所指向的空间的值的时候,需要在指针前面加上*解引用符号,因为我们的指针是指向内存中某一处空间里的变量,所以在使用的时候如果改变该指针指向的空间的值,存储在该空间的变量的值也会发生改变。
int num = 9;
int* ptr_num = #
printf("%d\n", num);//9
printf("%d\n", *ptr_num);//9
*ptr_num = 1;
printf("%d\n", num);//1
printf("%d\n", *ptr_num);//1
传值调用和传址调用
我们都知道,函数的形参是对实参的一份临时拷贝,在函数中改变形参的变量并不会改变实参的变量。我们就不能通过函数来改变实参的值,现在我们学习了指针,就可以实现实参的值的改变了。我们通过一个交换两数的值的小案列来讲解一下。
传值调用
void swap(int a, int b) { //实参的临时拷贝
int c = a;
a = b;
b = c;
}
int main() {
int a = 3;
int b = 8;
printf("交换前:\n a = %d , b = %d\n", a, b); //a = 3, b = 8
swap(a, b); //将变量的值传给函数
printf("交换后:\n a = %d , b = %d\n", a, b); //a = 3, b = 8
return 0;
}
可以看到,函数在进行传值调用的时候,改变形参的值不会改变实参的值,并不能起到交换两数的值的作用。
传址调用
void swap(int* a, int* b) { //使用指针接受变量的地址
int c = *a;
*a = *b;
*b = c;
}
int main() {
int a = 3;
int b = 8;
printf("交换前:\n a = %d , b = %d\n", a, b); //a = 3, b = 8
swap(&a, &b);//将变量的地址传给函数
printf("交换后:\n a = %d , b = %d\n", a, b); //a = 8, b = 3
return 0;
}
进行传值调用的时候,函数得到的是存储变量的地址,这时候就可以交换两数的值了。需要注意的是,在进行传址调用的时候是需要传地址的,函数接收是使用指针接收的,千万不要和传值搞混了。
指针的弊端
指针就像是一把双刃剑,我们可以灵活地使用指针来进行编写代码,达到我们想要的目的。但是如果指针使用不当的话就有可能造成系统的损坏。就像传址调用可以改变实参的值,如果我们使用了一个不知道指向何处的指针,那么就有可能改变一个系统的值,系统就有可能出问题。
野指针
野指针就是指向未分配或者已经释放的内存地址的指针。 当我们使用野指针的时候就有可能发生难以挽回的损失。所以在使用指针的时候我们要格外小心。
int* ptr; //野指针,局部变量没有赋初始值的时候会自动赋值为随机值
使用指针的注意事项
定义的时候我们需要及时将指针赋值,如果没有想赋的值我们可以让指针指向NULL
int* ptr = NULL;
在使用完动态内存后也需要使用free函数将内存释放。
int * buffer1;
buffer1 = (int*) malloc (100*sizeof(int));
free(buffer1);