指针,数组,以及他们作为函数参数,或是返回值的异同.这些都是让初学C++的人很头痛的事.
我这里只讲一下我对这些问题的研究与看法.不对的地方还请斧正.
首先我们要清楚尽管指针与数组在有些地方可以通用,但它们两个是不同的,这一点要切记.
首先我们先来看看它们声明时的区别,在32位系统中指针是一个4字节的变量或常量(变量与常量的区别我
就不说了看看书或上网搜搜吧).其存放的内容为一个地址值,也就是其指向的地址值.
而数组是一个连续的存放相同数据类型的数据结构,我们通常所说的数组名就是指向其数组首地址的指针,
这句话没错,但就我的理解它还不是一个真正意义上的指针.因为并没有一块内存是用来单独存放这个地址
的.
我们可以用sizeof()操作符来证明这一点,sizeof一个指针和一个数组名得到的结果是不同的(除非你的数组长度和指针长度相同).
在作为函数参数传递的时候,指针与数组是相同的,这个我们众所周知.所谓的传值与传址,其实都是传值,
都是将原值的拷贝传给函数.只不过当传递指针的时候传递的是指针的值(就是其指向的地址).当传递数组
的时候同样是传递的数组的首地址(把首地址作为一个值传递给函数).这就是为什么在函数内部我们可以
像操作一个指针一样操作一个传进来的数组,而在外面却不能这样做,看下面的例子:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1327ab569c1ae82736693a50b8e33378.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
到这里我们已经基本明白了指针与数组的区别,下面我们来看看让人比较迷惑的例子.
char * retstr()
{
char str[] = " hello world! " ;
printf(str);
return str;
}
int main()
{
char * ptr;
ptr = retstr();
printf(ptr);
return 0 ;
}
上面的程序编译不会出错,而只是给出了一个[Warning] address of local variable `str' returned的
警告.显然它没有达到我们的目地,继续看下面:
char * retstr()
{
char * str = " hello world! " ; // 注意这里
printf(str);
return str;
}
int main()
{
char * ptr;
ptr = retstr();
printf(ptr);
return 0 ;
}
这个程序能够很好的运行,也达到了我们返回一个指向字符串的指针并利用返回的指针显示字符串的目的.
但第一个程序为什么不行呢,这里就是它们作为返回值的不同地方了.严格来说,本地数组是不能作为函数
返回值的,其返回的值是指向系统栈的地址,这个地址的内容在函数返回的时候会被清楚,所以你不知道其
指向的内容到底是什么,这就是为什么在你执行第一个程序的时候会看到乱码了.
而第二个程序声明了一个本地指针,其指向的内容是一个常量,当然常量肯定是存放在系统堆上的,在函数
返回的时候函数把这个指针指向的地址返回,并将指针本身销毁.这是我们还保留这系统堆上的这个字符串
的地址,当然我们就可以用这个地址对其操作了.
还有一个比较有意思的关于指针作为参数的例子:
{
p = ( char * )malloc( 100 );
}
void Test( void )
{
char * str = NULL;
GetMemory(str);
strcpy(str, " hello world " );
printf(str);
}
这个程序将会崩溃,我们先看下面程序然后解释
{
* p = ( char * )malloc( 100 );
}
void Test( void )
{
char * str = NULL;
GetMemory( & str);
strcpy(str, " hello world " );
printf(str);
}
这个程序执行没有问题输出hello world.细心的人不用说已经知道原因了,这就是我们前面说过的,当指针的值作为参数传递时,其只是简单的将
自己的值拷贝给函数,而且函数肯定不会改变这个值.但函数可以改变这个值指向的内容.第二个函数就是利用传递给它的一个指向指针的指针,
来改变这个指针所指向的指针的内容的.
能力有限希望我表达清楚了.今天就说道这了.至于指针与数组的其他相关方面今后再说了.