指针和函数入参的理解

指针的内涵是什么?函数的参数的理解。 指针作为函数参数的理解。

示例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的一个指针。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值