
指针是一个值为内存地址的变量, 指针的核心是它是一个变量, 只不过它是用来存放内存地址的, 所以在了解指针之前,先说一下什么是变量。变量就是在内存中开辟的一个空间。如int year, 就是在内存中开辟了一个空间,空间名称为year, 开辟空间做什么呢?肯定是存放程序运行中所需要的东西,在计算机语言中,存放东西就是赋值。year= 2018, 给year赋值,就是在year这个空间中存放一个整数2018; 开辟了空间,也存放了数值,那我们要使用这个空间中的东西怎么办?我们怎样才能找到这个空间?当然,最简单的办法,是直接使用名称year, 其实还有一种办法,就是找到这个空间的地址,找到地址后,我们就可以做任何事情了。内存在开辟空间的时候,自动就会获得一个地址,这个地址就是内存地址,这和我们日常生活也是一样的道理。比如开发商拿了一块地,它就相当于开辟了空间。拿地的同时,也就是开辟空间的时候,它自动会有一个地址,他在广东省拿的地,地址肯定是广东省,而不是北京,并且地址在获得之后,也不会再发生变化。只不过地址描述方式不同,在现实生活中,它是广东省深圳市,而在计算机中,它是一个十六进制的数字, 0060FF08;
每一个变量都有地址,那怎么才能获取到变量地址呢?C语言提供了一个&运算符来获取内存地址,&year 就取得了year内存地址。 获取到地址后,肯定要操作这个地址,要不然,我们获取它做什么。操作它就要先保存起来,保存东西就是用 变量,所以还要声明一个变量,由于这个变量是用来保存内存地址的,所以变量的声明也不太一样,在变量之前加了一个*号。 int *pointer_year., pointer_year 就可以保存整型变量的地址。由于变量year也是一个整型,所以就可以把year的地址存放到pointer_year中。 pointer_year = &year, pointer_year 保存的是year的内存地址,这时也可以称之为pointer_year 指向了year,所以就给point_year变量起了一个名称------指针。指针变量和普通变量一样,都是用保存东西的。但又有所区别,它保存的是另一个变量的内存地址,可以通过它找到另一个变量,从来操作另一个变量。 还要注意一点:指针变量有一个特殊的常量,NULL, 表示为空, 如point_year = NULL, 表示指针不指向任何地址,可以用它来初始化指针变量,也可以用它来释放内存。
int main() { ; int * pointer_year = &year; printf("the memory address for year is %p \n", pointer_year); pointer_year = NULL; printf("the memory address for year is %p", pointer_year); ; }
现在我们有了变量的地址,也保存起来了,那就可以顺藤摸瓜地找到内存地址对应的空间,也就是相对应的变量。运算符还是用*, *pointer_year,就会获取到pointer_year内存地址所对应的空间。pointer_year只是一个地址,就相当于黄页中的汉字,只是写着广东省深圳市这几个字,要想做什么事,肯定要真正到这个地方去。*运算符,就相当于我们驾车到广东省深圳市这个地方作考察。只要到了这个地方,我们就可以做任何事情了,比如建工厂,盖房子。*pointer_year,就相当于到了它所指向的内存空间,那么就可以查看,修改。*point_year = 10;就是对pointer_year指向的内存空间进行了修改。当* 作为运算符的时候,叫做取地址所对应的值,所以它只能放在指针变量的前面, 取出地址所指向的值,那就是变量。*point_year 的值就是变量year. *point_year = 10; 其实就是对量year赋值。
int main() { ; int * pointer_year = &year; printf("year变量的内存地址 %p \n", pointer_year); *pointer_year = ; printf("year变量通过地址进行修改,修改后的值为%d\n", year); ; }
指针变量也是变量,所以它也有地址,&point_year 就是取指针变量对应的地址。它是一个地址,所以还要声明一个指针变量 int ** pointer_p_year = &point_year. 这里要注意,声明变量的时候,要有两个**
int main() { ; int * pointer_year = &year; // 取指针变量pointer_year 的地址存放到 pointer_p_year变量中 int ** pointer_p_year = &pointer_year; // 打印地址 printf("year变量的内存地址 %p \n", pointer_year); printf("指针变量pointer_year的内存地址 %p \n", pointer_p_year); ; }
那么我们*运算符也是可以取地址,*pointer_p_year 返回的是point_year, 然而它也是一个指针变量,*point_year 才是指向的变量。**pointer_p_year 批向了year, **pointer_p_year = 10, 同样是给它变量year赋值。
int main() { ; int * pointer_year = &year; // 取指针变量pointer_year 的地址存放到 pointer_p_year变量中 int ** pointer_p_year = &pointer_year; // 打针地址 printf("指针变量pointer_year的内存地址 %p \n", pointer_p_year); // 通过地址的地址修改变量值 **pointer_p_year = ; printf("变量year的值 %d \n", year); ; }
指针与数组:
数组是在内存中开辟的一块连续的内存空间, 而数组名则是这块连续内存空间的首地址, 首地址其实就是数组第一个元素的地址。知道了首地址,又是连续的内存空间,我们就可以通过移动指针来访问数组中的元素。怎么才能移动指针呢? 使用 +或-号, 当指针加1的时候,它就会指向下一个内存地址。一个类型为T的指针的移动,以sizeof(T) 为移动单位, sizeof 是一个函数,接受一个元素或数据类型作为参数,返回这个元素或类型所占的内存空间。int * p; 执行 p + 1; 指针p 就会移动sizeof(int), 4个 字节。
数组也可以存放指针类型的数据。
Int * arr[]; // arr数组是一个指针数组,数组中所有的元素都保存指针。 ; ; ; arr[] = &one; arr[]= &two; arr[] = &three;
指针与函数
如果一个函数可以接受任何类型的指针变量,可以把这个函数参数设为void *;
Int add(void *data); // add 函数可以接受任意类型的指针变量。
函数指针: 重点是指针,指向函数的指针,它的声明的方式有点奇怪
函数类型 (*指针变量名)(形参列表);第一个括号一定不能少。
Int (*add)(int a, int b); // add 变量 就可以指向一个函数. int f(a, b); add = f; (*add)(, ); // 调用函数指针
指针函数:重点是函数,只不过它返回的是一个指针。Int * add();