C语言指针难吗?纸老虎而已,纯干货讲解( 四 )


int a ; //int类型变量 aint *a ; //int* 变量aint arr[3]; //arr是包含3个int元素的数组int (* arr )[3]; //arr是一个指向包含3个int元素的数组的指针变量//-----------------各种类型的指针------------------------------int* p_int; //指向int类型变量的指针 double* p_double; //指向idouble类型变量的指针 struct Student *p_struct; //结构体类型的指针int(*p_func)(int,int); //指向返回类型为int,有2个int形参的函数的指针 int(*p_arr)[3]; //指向含有3个int元素的数组的指针 int** p_pointer; //指向 一个整形变量指针的指针指针的2个重要属性
指针也是一种数据,指针变量也是一种变量,因此指针 这种数据也符合前面变量和内存主题中的特性 。
这里要强调2个属性:指针的类型,指针的值 。
int main(void){ int num = 97; int *p1 = # char* p2 = (char*)(&num); printf("%d",*p1); //输出 97 putchar(*p2); //输出 a return 0;}指针的值:很好理解,如上面的num 变量,其地址的值就是0028FF40,因此 p1的值就是0028FF40 。
数据的地址用于在内存中定位和标识这个数据,因为任何2个内存不重叠的不同数据的地址都是不同的 。
指针的类型:指针的类型决定了这个指针指向的内存的字节数并如何解释这些字节信息 。
一般指针变量的类型要和它指向的数据的类型匹配 。
由于num的地址是0028FF40,因此 p1 和 p2 的值都是0028FF40
*p1 : 将从地址0028FF40 开始解析,因为p1是int类型指针,int占4字节,因此向后连续取4个字节,并将这4个字节的二进制数据解析为一个整数 97 。
*p2 : 将从地址0028FF40 开始解析,因为p2是char类型指针,char占1字节,因此向后连续取1个字节,并将这1个字节的二进制数据解析为一个字符,即'a' 。
同样的地址,因为指针的类型不同,对它指向的内存的解释就不同,得到的就是不同的数据 。
取地址
既然有了指针变量,那就得让他保存其它变量的地址,使用& 运算符取得一个变量的地址 。
int add(int a , int b){ return a + b;}int main(void){ int num = 97; float score = 10.00F; int arr[3] = {1,2,3}; //----------------------- int* p_num = # float* p_score = &score; int (*p_arr)[3] = &arr; int (*fp_add)(int ,int ) = add; //p_add是指向函数add的函数指针 return 0;}特殊的情况,他们并不一定需要使用&取地址:

  • 数组名的值就是这个数组的第一个元素的地址 。
  • 函数名的值就是这个函数的地址 。
  • 字符串字面值常量作为右值时,就是这个字符串对应的字符数组的名称,也就是这个字符串在内存中的地址 。
int add(int a , int b){ return a + b;}int main(void){ int arr[3] = {1,2,3}; //----------------------- int* p_first = arr; int (*fp_add)(int ,int ) = add; const char* msg = "Hello world"; return 0;}解地址
我们需要一个数据的指针变量干什么?
当然使用通过它来操作(读/写)它指向的数据啦 。
对一个指针解地址,就可以取到这个内存数据,解地址的写法,就是在指针的前面加一个*号 。
解指针的实质是:从指针指向的内存块中取出这个内存数据 。
int main(void){ int age = 19; int*p_age = &age; *p_age = 20; //通过指针修改指向的内存数据 printf("age = %d",*p_age); //通过指针读取指向的内存数据 printf("age = %d",age); return 0;}指针之间的赋值
指针赋值和int变量赋值一样,就是将地址的值拷贝给另外一个 。
指针之间的赋值是一种浅拷贝,是在多个编程单元之间共享内存数据的高效的方法 。
??????int* p1 = & num;int* p3 = p1;//通过指针 p1 、 p3 都可以对内存数据 num 进行读写,如果2个函数分别使用了p1 和p3,那么这2个函数就共享了数据num 。 
C语言指针难吗?纸老虎而已,纯干货讲解

文章插图
 
空指针(NULL指针)
NULL是C语言标准定义的一个值,这个值其实就是0,只不过为了使得看起来更加具有意义,才定义了这样的一个宏,中文的意思是空,表明不指向任何东西 。你懂得 。不过在此不讨论空和零的区别 。
在C语言中,我们让指针变量赋值为NULL表示一个空指针,而C语言中,NULL实质是((void*)0),就像前面说的指针可以理解成特殊的int,它总是有值的,p=NULL,其实就是p的值等于0 。对于不多数机器而言,0地址是不能直接访问的,设置为0,就表示该指针哪里都没指向 。而在C++中,NULL实质是0 。
换种说法:任何程序数据都不会存储在地址为0的内存块中,它是被操作系统预留的内存块 。


推荐阅读