1. 一维指针做函数参数
传入的指针为NULL
比如下面的例子,很多人都会理解错:
#include <stdio.h>
void test(char *string)
{
string = "hello world";
}
int main()
{
char *str = NULL;
test(str);
printf("str=%s\n",str);
return 0;
}
是不是觉得输出应该是:str=hello world.事实上并不是
输出结果是(操作系统:win10):
具体过程如下:
开始str指针指向NULL,并将该地址作为形参传入函数test(),最开始string指针也是指向NULL,接着讲“hello world”地址传给了string,此时string的指针不再指向NULL,而是指向“hello world”这个字符串的地址。为了验证这个,可以在代码里加一些打印信息验证:
#include <stdio.h>
void test(char *string)
{
printf("string未操作之前的的指针:%p\n",string);
string = "hello world";
printf("string未操作之后的的指针:%p\n",string);
}
int main()
{
char *str = NULL;
printf("传入test函数之前str的指针:%p\n",str);
test(str);
printf("str=%s\n",str);
getchar();
return 0;
}
结果:
2.那要实现在test函数中改变str的指针指向地址怎么办?
2.1 返回string指针,这个很好理解
#include <stdio.h>
char *test(char *string)
{
string = "hello world";
return string;
}
int main()
{
char *str = NULL;
str = test(str);
printf("str=%s\n",str);
getchar();
return 0;
}
结果:
2.2 用二维指针
#include <stdio.h>
void test(char **string)
{
*string = "hello world";
}
int main()
{
char *str = NULL;
test(&str);
printf("str=%s\n",str);
getchar();
return 0;
}
结果:
具体分析如下图:
过程:
1.定义一个字符串指针str,str本身的地址是100,值为0(即NULL,一般的编译器NULL的地址是0)。
2.取str的地址100传给string,此时string的值是100,地址为200
3.这里假设“hello world”字符串的地址是300,接下来就是改变一级指针指向的内容的地址,由0变成300。
针对评论区的留言,再一起讨论学习下:
问题:为什么传入形参的是指针,在test函数调用后,main函数中str的内容没有改变?
先看几个例子:
#include <stdio.h>
#include <string.h>
void test(char *string)
{
char *testString = "world";
printf("111 string addr:%p, testString addr:%p\n",string,testString);
string = testString;
printf("222 string addr:%p, testString addr:%p\n",string,testString);
}
int main(void)
{
char *str ="china";
test(str);
printf("333 str addr:%p, str is:%s\n",str,str);
return 0;
}
结果(因为用的是64位系统,所以地址是8位,这里地址显示的6位,因为前面两位是0,所以默认省略了):
形参都是值传递。但是这个值如果是指针的话,是可以改变指针指向内容的值,即实参的值。这个要弄清两个概念:指针和指针指向的数据。
这个例子中形参的值是实参的地址,并不是实参的值,所以形参的值的改变只是指针的改变,即指向数据的地址改变,并不是指针指向数据的改变。所以我们发现在main函数中,str的值没有改变。
我们先再看一个例子:
#include <stdio.h>
#include <string.h>
void test(char *string)
{
printf("111 addr:%p, content:%s\n",string,string);
strncpy(string,"world",6);//连带把字符串结尾复制过去
printf("222 addr:%p, content:%s\n",string,string);
}
int main(void)
{
char *str ="china";
test(str);
printf("333 addr:%p, content:%s\n",str,str);
return 0;
}
结果:
编译没有任何问题。但是运行却崩溃了,为什么呢?
这个又是一个需要注意的点:指针指向的常量存储区是不允许修改的,这个实参和形参的地址都是指向字符串的地址,是const类型的,所以不能修改。
原来的程序稍作修改:
#include <stdio.h>
#include <string.h>
void test(char *string)
{
printf("111 addr:%p, content:%s\n",string,string);
strncpy(string,"world",6);//连带把字符串结尾复制过去
printf("222 addr:%p, content:%s\n",string,string);
}
int main(void)
{
char str[] ="china";//修改这里,用字符数组存储,这样指针就指向栈区的内容了
test(str);
printf("333 addr:%p, content:%s\n",str,str);
return 0;
}
结果:
我们可以看到,地址没有改变,但是内容已经被修改了。
总结:
形参都是值传递。
1.这个值是指针的话,在被调用的函数(test)中,如果指针的值,不会改变实参的值。
2.如果改变指针指向的内容时,会改变实参的值。
注意:在传递的过程中如果是const类型的指针是不允许修改的。