一级指针做形参:首先一定要明白形参和你传递参数的那个实参是两个不同的变量,即使同名也还依然不同。指针传递的是一个变量或者一个值的地址,但是它本身还是采用值传递的方式。即你不能使它指向另外一块地址,但是你可以改变它指向的空间里存的值。
二级指针做形参:二级指针也是传值,但是他指向的地址是个一维指针,所以可以改变二维指针指向的地址空间里的内容也就是要申请空间的一维指针,不能改变二维指针本身的值,即不能让他指向一个新的一维指针。所以二维指针传递的是一个一维指针。
具体看下面这个程序以及输出:
- #include<stdio.h>
- #include <malloc.h>
- #include <string.h>
- void GetMemory1(char *p)
- {
- //该函数的形参为字符指针,在函数内部修改形参并不能真正改变传入形参的实参值。
- //因此在主函数中执行完下面两句之后
- //char *str1 = NULL;
- //GetMemory1(str1);
- //str1仍然为NULL,因此会报内存错误,没有输出结果。
- p = (char *)malloc(100);
- //要记得使用指针变量时,每次分配空间后要判断是否分配成功。而且在主函数中使用之后记得释放内存,并置空
- if (p == NULL)
- {
- printf("error memory");
- }
- }
- /*但是上面的函数参数变为*char *&p就可以在主函数中正常输出了。
- 指针做形参也是采用值传递的方式,也就是会把指针的值-地址传过去,所以可以改变这个地址里的内容,
- 但是你不能改变指针的值,也就是指向的地址。但是引用就是变量的别名,所以可以改变指针的值,
- 所以就可以在函数里申请空间*/
- char *GetMemory2(void)
- {
- <SPAN style="COLOR: #ff0000">char p[] = "hello world";
- return p; //p[]数组为函数内部局部变量,在函数返回后,内存已经被释放了,
- //所以在主函数中调用该函数str2 = GetMemory2();输出的可能为乱码</SPAN>
- }
- void GetMemory3(char **p,int num)
- {
- *p = (char *)malloc(num);
- //要记得使用指针变量时,每次分配空间后要判断是否分配成功。而且在主函数中使用之后记得释放内存,并置空
- if (*p == NULL)
- {
- printf("error memory");
- }
- }
- void main()
- {
- int n=0;
- char *str1 = NULL;
- char *str2 = NULL;
- char *str3 = NULL;
- //GetMemory1(str1);
- //strcpy(str1,"Hello world");
- //printf("%s\n",str1);
- str2 = GetMemory2();
- printf("%s\n",str2);//输出乱码
- GetMemory3(&str3,100);
- strcpy(str3,"hello world");
- printf("%s\n",str3);//输出hello world
- char *str4 = (char *)malloc(100);
- if (str4 == NULL)
- {
- printf("error memory");
- }
- else
- {
- strcpy(str4,"Hello");
- free(str4);
- str4 == NULL;//free后要置空,否则str可能变成“野指针”
- }
- if (str4 != NULL)
- {
- strcpy(str4,"world");
- printf("%s\n",str4);//输出world
- }
- scanf("%d",&n);
- }
#include<stdio.h>
#include <malloc.h>
#include <string.h>
void GetMemory1(char *p)
{
//该函数的形参为字符指针,在函数内部修改形参并不能真正改变传入形参的实参值。
//因此在主函数中执行完下面两句之后
//char *str1 = NULL;
//GetMemory1(str1);
//str1仍然为NULL,因此会报内存错误,没有输出结果。
p = (char *)malloc(100);
//要记得使用指针变量时,每次分配空间后要判断是否分配成功。而且在主函数中使用之后记得释放内存,并置空
if (p == NULL)
{
printf("error memory");
}
}
/*但是上面的函数参数变为*char *&p就可以在主函数中正常输出了。
指针做形参也是采用值传递的方式,也就是会把指针的值-地址传过去,所以可以改变这个地址里的内容,
但是你不能改变指针的值,也就是指向的地址。但是引用就是变量的别名,所以可以改变指针的值,
所以就可以在函数里申请空间*/
char *GetMemory2(void)
{
<span style="color:#ff0000;">char p[] = "hello world";
return p; //p[]数组为函数内部局部变量,在函数返回后,内存已经被释放了,
//所以在主函数中调用该函数str2 = GetMemory2();输出的可能为乱码</span>
}
void GetMemory3(char **p,int num)
{
*p = (char *)malloc(num);
//要记得使用指针变量时,每次分配空间后要判断是否分配成功。而且在主函数中使用之后记得释放内存,并置空
if (*p == NULL)
{
printf("error memory");
}
}
void main()
{
int n=0;
char *str1 = NULL;
char *str2 = NULL;
char *str3 = NULL;
//GetMemory1(str1);
//strcpy(str1,"Hello world");
//printf("%s\n",str1);
str2 = GetMemory2();
printf("%s\n",str2);//输出乱码
GetMemory3(&str3,100);
strcpy(str3,"hello world");
printf("%s\n",str3);//输出hello world
char *str4 = (char *)malloc(100);
if (str4 == NULL)
{
printf("error memory");
}
else
{
strcpy(str4,"Hello");
free(str4);
str4 == NULL;//free后要置空,否则str可能变成“野指针”
}
if (str4 != NULL)
{
strcpy(str4,"world");
printf("%s\n",str4);//输出world
}
scanf("%d",&n);
}
下面是中兴通讯2012校招笔试题目,问输出什么?
- #include <stdio.h>
- //此函数中d也是个局部变量,函数执行完自动销毁,但是指针分配的空间不会被自动回收,除非程序员delete掉。
- //所以这个可以正常输出。
- <SPAN style="COLOR: #ff0000">char *a()
- {
- char *d = "ZET";//这个初始化的一种形式,相当于分配了四个空间 ,这有点不好理解!照说d是局部变量啊。要销毁的啊,应该输出乱码啊。实际上特殊在“ZET”存储 在常量区,而常量区是在程序结束时才释放的。故此地址仍有效!可以认为这是C/C++语言不合理的地方。
- return d;
- }</SPAN>
- //但是第二个数组空间是系统维护的,函数执行完自动销毁
- char *b()
- {
- char p[10] = {"3G平台"};
- return p;
- }
- //参数是值传递方式,改变形参的地址,传递的实参的地址确不会因此改变
- void c(int n,char *pName)
- {
- char *a[4] = {"aaa","bbb","ccc","ddd"};
- pName = a[n];
- }
- void main()
- {
- int n=0;
- char *pName = "DB";
- printf("%s\n",a());//输出ZET
- printf("%s\n",b());//随机输出乱码
- c(2,pName);
- printf("%s\n",pName); //输出DB,因为char *pName = "DB";已经使得pName指向了DB,但c(2,pName);并不能改变pName指向的地址。
- //形象点说就是:我有一个箱子给你用,你可以在里面装东西,但是你不能把我的箱子换成另外一个给我。
- //在这里指的是不能函数调用不能使pName变成函数中的二维数组a。
- scanf("%d",&n);
- }