指针的内涵是什么?函数的参数的理解。 指针作为函数参数的理解。
示例1
#include <stdio.h>
#include <stdlib.h>
void test01(char* q){
q = (char*)malloc(sizeof(char*));
}
int main()
{
char *p = NULL;
test01(p);
if(!p){
printf("p为null\n");
}
return 0;
}
结果是打印 p = null;
示例2:
#include <stdio.h>
#include <string.h>
void test02(char* q){
char str[] = "string";
memcpy(q,"str",sizeof(str));
}
int main()
{
char p[16];
test02(p);
printf("p = %s\n",p);
return 0;
}
正常输出 p = str;
示例3
#include <stdio.h>
#include <string.h>
void test02(char* q){
char str[] = "string";
memcpy(q,"str",sizeof(str));
}
int main()
{
char *p = NULL;
test02(p);
if(!p){
printf("p = null\n");
}
return 0;
}
发生段错误。
示例1 对比示例2 :为什么都是传入指针?而且示例1 却没有达到想要的结果呢?
这就要明白两个关键点:
(1) 指针就是地址;
(2) 函数的入参是临时变量。 即便参数类型是指针,它也是临时变量,或者说是一个副本,函数运行完变量消失。(这个结论,没有验证过,可能看汇编能理解)
这样就可以理解了
示例1 中, char * p = NULL; 什么意思呢? 那么在考虑一下,char q[8]。这里p 和q 都是指针,根据q理解指针的意思,这个q指针就是这个char数组的首地址,那么p是什么意思呢?p也是地址,它的意思是p的地址指向NULL。指向空,什么意思,就是P没有指向一个地址。这个指针,没有指向地址,也就是空指针,没有指向地址也就是没有指向内存。
这样就可以理解这个程序 了,所以p 指针传入函数了,但是其实是它的副本,而且函数执行完,这个副本就消失了,所以p还是p 还是空指针,指针并没有变化,所以p= NULL。
示例2 为什么达到目的呢?示例2可以知道,这是p 指向一个数组了,是一个数组的首地址,这时p 传入函数,当然还是p的副本,这时情况与示例1不同了,因为即便是副本,这个副本也是一个地址,指向数组首地址,所以下边操作这个副本,也能找到那个数组,因为指针(地址)还是一样的嘛。当然函数执行完,副本消失,但p还是指向数组首地址的。
总结示例1 示例2 可以得出,指针作为参数变量,和普通变量是一样的,(毕竟底层(函数的实现原理)又不区分他是指针还是变量,对待方式肯定是一样的),都是副本,函数执行完副本消失,传入的指针(或者变量)其实是没有变化的,比如 示例1 中和示例2中 p指针都没有变化,那示例2 之所以能 达到目的,也是因为它没有改变p ,而是改变p指向的内存的值。
这样再看示例3 就好理解了:
为什么发生段错误,首先p是空指针,根据上面说的知道,空指针就是 没有指向内存,就是没有存储空间。想当于空指针只是一个符号,这个符号不像其他变量(普通变量)有存储空间;所以这个空指针传入函数,就是它的副本传入函数,它副本还是空指针,那么 执行memcpy(q,"str",sizeof(str)); 就是相当于向一个没有内存的指针,写入数据,那自然是不合理的,它没有内存可以写,所以发生了段错误。
示例1 改改,如何给空指针赋值呢?
示例4;
#include <stdio.h>
#include <stdlib.h>
void test01(char** q){
char *r = NULL;
r = (char*)malloc(sizeof(char*));
*q = r;
}
int main()
{
char *p = NULL;
test01(&p);
if(p){
printf("p = %p\n",p);
}
if(!p){
printf("p = null\n");
}
return 0;
}
结果输出;p = 0xce2010 (这个值,不是一定的。)
示例4 怎么分析呢? *q = r 可以不可换为 q = &r呢?
首先分析:
p 是空指针。应该理解,空指针也是一个变量, &p 就是取这个p指针变量的地址,可以理解为,&p这个地址的内存单元保存了p指针。
所以,把&p作为参数传进去,它的一个副本肯定还是这个地址,地址是同样的,这个地址代表的内存里保存的还是 p指针(也是空指针); r = (char*)malloc(sizeof(char*)); 这条语句得到,r 指针指向一个内存地址。然后 主要就是 *q = r 这一句,怎么理解,q是&p的副本,它指向的内存保存的是P指针,也是*q,解引用得到的就是 p指针了,所以 就相当于 p = r了 那么这就给 p 赋上值了。
那么有个问题 *q = r 和 q = &r 一样吗?能用 q = &r 吗?
再分析一下, 知道q是&p的副本,&r上面意思呢?就是 &r是取r指针的地址,那么q = &r ,就是q指向 r指针(变量)的地址了;就是说,原来q是&p的副本,q指向p指针(变量)的地址,现在q指向r指针(变量)的地址了,那这样 与p指针 是没有关系的。p指针 肯定还是空指针。
所以 如果 示例4 *q = r 换为 q = &r,p指针还是空指针。所以输出 是: p = null;
知识点: char **p ,二级指针, 这可以理解为 (char*)* p这样, 把char* 当作一个类型,所以char**p 意思就是 p指针 指向一个 char* ; 然后这个char * 就是 指向 char 的指针。 所以理解起来就是 char** p 就是 , p指向一个 指针,这个指针指向char。 也即是 p是一个指向char类型的指针的指针。
所以: 如果 p 是char* 类型(char*p ),那么&p的类型就是 char** 类型。 因为&p 就是 取 p的地址,或者说&p是指向p的一个指针。