#include<iostream>
using namespace std;
int GetMemory(char **pp1, char **pp2)
{
char a[] = "hello";
char *b = "world";
*pp1 = a; //----?A
*pp2 = b; //----?B
return 0;
}
int main()
{
char *p1, *p2;
GetMemory(&p1 , &p2 );
cout<<p1<<endl; //---?C
cout<<p2<<endl; //---?D
system("pause");
}
首先,第一行肯定是输出乱码,解释2个知识点你就知道了:
1.数组和指针的区别,其实对于你的问题这不是最重要的,不过既然你问道区别就说说吧:
数组名确实表示指向数组首地址的指针,但这个指针很特别,它的值(指针的值指的是指针所指的地址)不能被改写,
能改写的仅仅是其指向的内容,换句话说,数组名只能指向数组的首地址,如果有数组char a[];那么如果出现a = a+1;
这是编译都通不过的错误。而对于一个普通的指针是可以的,再比如有数组char a[];那么再定义一个char *p = a;
然后再用p = p+1是合法的,这表示让指针p指向&a[1]。
它们的第二个区别是:每当用到数组名这个指针的时候,系统都会传入数组的信息,而普通的指针只是一个4字节的整数,例如:
char a[5];
char *p = a;//指针a和指针p都指向数组a的首地址
cout << sizeof (a) << "##" << sizeof (p) << endl;
这时的运行结果是“5##4”
2.作用域以及生存期:
被一组“{}”括起来的部分被称为一个“域”,在某个域中定义的变量称为局部变量,这个局部变量仅仅在该作用域下有效,一旦离开这个作用域,该变量就消亡;如果遇见多重作用域,外层的变量可在内层起作用,如果遇见内层与外层同名的情况,则内层的同名变量在内层覆盖外层变量。
举个例子:
void fun1()
{
int a = 1;//在fun1()中定义整型变量a值为1
}
void fun2()
{
cout << a << endl;//企图在fun2()中使用fun1()中的变量,编译出错!因为a在离开其作用域后消亡,这里会提示变量a没有被声明;
}
void fun3 ()
{
int c = 1;
cout << c << endl;//正常打印出c的值,即1;
{ //新增加作用域
int c = 2; //在fun3()的子作用域中定义重名变量c,注意,如果不是子作用域编译会报错,因为重复定义同一个变量
cout << c << endl;//这里将打印出子作用域的c,即2,这里说明了新增的c覆盖了上面的c;
} //新增加的作用域结束
cout << c << endl;//这里依然会打印出1,因为这里的c是第一个定义的c,上面新增的作用域的c已经在其作用域结束的时候消亡。
}
好了,上面的基础知识说完了,现在我们来分析你的程序,第一行出现乱码是因为在函数GetMemory()结束的时候,数组消亡了,
每个元素都消亡了,所以在你打印的时候,系统找不到p1指向的值,因为已经消亡,p1成了野指针,所以出现乱码
,而第二行正常是因为:虽然指针b也在函数中消亡,不过消亡的仅仅只是一个指针,
其指向的内容并没有消亡,而这些内容的首地址已经在GetMemory()中赋给了你传入的指针,所以第二行正确
using namespace std;
int GetMemory(char **pp1, char **pp2)
{
char a[] = "hello";
char *b = "world";
*pp1 = a; //----?A
*pp2 = b; //----?B
return 0;
}
int main()
{
char *p1, *p2;
GetMemory(&p1 , &p2 );
cout<<p1<<endl; //---?C
cout<<p2<<endl; //---?D
system("pause");
}
首先,第一行肯定是输出乱码,解释2个知识点你就知道了:
1.数组和指针的区别,其实对于你的问题这不是最重要的,不过既然你问道区别就说说吧:
数组名确实表示指向数组首地址的指针,但这个指针很特别,它的值(指针的值指的是指针所指的地址)不能被改写,
能改写的仅仅是其指向的内容,换句话说,数组名只能指向数组的首地址,如果有数组char a[];那么如果出现a = a+1;
这是编译都通不过的错误。而对于一个普通的指针是可以的,再比如有数组char a[];那么再定义一个char *p = a;
然后再用p = p+1是合法的,这表示让指针p指向&a[1]。
它们的第二个区别是:每当用到数组名这个指针的时候,系统都会传入数组的信息,而普通的指针只是一个4字节的整数,例如:
char a[5];
char *p = a;//指针a和指针p都指向数组a的首地址
cout << sizeof (a) << "##" << sizeof (p) << endl;
这时的运行结果是“5##4”
2.作用域以及生存期:
被一组“{}”括起来的部分被称为一个“域”,在某个域中定义的变量称为局部变量,这个局部变量仅仅在该作用域下有效,一旦离开这个作用域,该变量就消亡;如果遇见多重作用域,外层的变量可在内层起作用,如果遇见内层与外层同名的情况,则内层的同名变量在内层覆盖外层变量。
举个例子:
void fun1()
{
int a = 1;//在fun1()中定义整型变量a值为1
}
void fun2()
{
cout << a << endl;//企图在fun2()中使用fun1()中的变量,编译出错!因为a在离开其作用域后消亡,这里会提示变量a没有被声明;
}
void fun3 ()
{
int c = 1;
cout << c << endl;//正常打印出c的值,即1;
{ //新增加作用域
int c = 2; //在fun3()的子作用域中定义重名变量c,注意,如果不是子作用域编译会报错,因为重复定义同一个变量
cout << c << endl;//这里将打印出子作用域的c,即2,这里说明了新增的c覆盖了上面的c;
} //新增加的作用域结束
cout << c << endl;//这里依然会打印出1,因为这里的c是第一个定义的c,上面新增的作用域的c已经在其作用域结束的时候消亡。
}
好了,上面的基础知识说完了,现在我们来分析你的程序,第一行出现乱码是因为在函数GetMemory()结束的时候,数组消亡了,
每个元素都消亡了,所以在你打印的时候,系统找不到p1指向的值,因为已经消亡,p1成了野指针,所以出现乱码
,而第二行正常是因为:虽然指针b也在函数中消亡,不过消亡的仅仅只是一个指针,
其指向的内容并没有消亡,而这些内容的首地址已经在GetMemory()中赋给了你传入的指针,所以第二行正确