当前位置:网站首页>C语言的指针

C语言的指针

2022-06-21 14:45:00 用户6978604

指针作为参数传递

C语言中,当指针作为函数参数进行传递时,实际上形参和实参指向的是同一个地方,例如:

/*
 * @Author: YaleXin
 * @Date: 2020-06-19 18:02:53
 * @LastEditTime: 2020-06-29 08:59:40
 * @LastEditors: YaleXin
 * @Description:
 * @FilePath: \my_c_workspace\some_test\pointTest-copy.c
 * @祈祷不出现BUG
 */
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
void test(int *p1) { printf("=== test p1 = %p ====\n", p1); }
int main() {
    int *p;
    printf("=== main p = %p ====\n", p);
    test(p);
    return 0;
}

输出的是:

=== main p = 0000000000000010 ====
=== test p1 = 0000000000000010 ====

可见二者的地址是相同的。

所以形参对其指向的内存区域进行修改,也会影响到实参指向的内存区域,因为二者指向的区域是同一个位置,例如:

/*
 * @Author: YaleXin
 * @Date: 2020-06-19 18:02:53
 * @LastEditTime: 2020-06-29 09:08:30
 * @LastEditors: YaleXin
 * @Description:
 * @FilePath: \my_c_workspace\some_test\pointTest-copy.c
 * @祈祷不出现BUG
 */
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
void test(int *p1) { *p1 = 2; }
int main() {
    int a = 1;
    int *p = &a;
    printf("before a = %d\n", a);
    test(p);
    printf("after a = %d\n", a);
    return 0;
}

输出的是:

before a = 1
after a = 2

但是,我们再来看一个例子:

/*
 * @Author: YaleXin
 * @Date: 2020-06-19 18:02:53
 * @LastEditTime: 2020-06-29 09:16:55
 * @LastEditors: YaleXin
 * @Description:
 * @FilePath: \my_c_workspace\some_test\pointTest-copy.c
 * @祈祷不出现BUG
 */
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
void test(char *p1) { p1 = "modified"; }
int main() {
    char *p = NULL;
    test(p);
    printf("after p = %s\n", p);
    return 0;
}

很容易让人以为输出的是

after p = modified

但是实际上输出的是

after p = (null)

下图给出这个过程中,指针的变化:

实际上是因为形参指向的区域已经与实参指向的不一致。

但是假如有在被调函数改变实参的地址的需求怎么办?

两种方法:

被调函数返回指针:

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
char *test(char *p1) { p1 = "modified"; }
int main() {
    char *p = NULL;
    p = test(p);
    printf("after p = %s\n", p);
    return 0;
}

但是使用该方法的时候,不推荐返回局部指针,返回局部指针很容易出现错误,详见这篇文章

下面的例子就是存在问题:

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
char *test(char *p1) {
    p1 = "modified";
    char str[20] = "";
    sprintf(str, "yalexin %s", p1);
    printf("str = %s\n",str);
    return str;
}
int main(void) {
    char *p = NULL;
    p = test(p);
    printf("after p = %s\n", p);
    return 0;
}

输出的是:

str = yalexin modified
after p = (null)

使用二级指针:

#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
char test(char **p1) { *p1 = "modified"; }
int main(void) {
    char *p = NULL;
    printf("调用函数之前p的地址是 %p\n", p);
    test(&p);
    printf("调用函数之后p的地址是 %p\n", p);
    printf("after p = %s\n", p);
    return 0;
}

输出:

调用函数之前p的地址是 0000000000000000
调用函数之后p的地址是 0000000000404000
after p = modified

注意事项

  1. 当指针指向的是一个变量,例如*int* *p = &a;,是不能使用free(p)进行释放资源, free() 只是针对使用了 malloc()realloc()函数进行申请的内存进行释放。
  2. 使用free()后,相应的指针就会变为“野指针”,如果对野指针进行引用,会造成不可预期的后果,所以一般使用free(p)后,一般紧接着p = NULL
原网站

版权声明
本文为[用户6978604]所创,转载请带上原文链接,感谢
https://cloud.tencent.com/developer/article/2027227