关于局部指针变量和数组的操作返回值

本文深入解析C++中数组与指针的基本概念,包括它们的区别以及作用域原则。通过实例代码,清晰展示了数组名与普通指针的不同特性,以及作用域如何影响变量的有效范围。
#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()中赋给了你传入的指针,所以第二行正确
### C/C++ 中函数返回结构体数组 #### 定义声明 为了使函数能够返回结构体数组,在C/C++中可以采用多种方式。一种常见的方式是利用指针间接返回,因为直接返回大尺寸的结构体数组可能导致效率低下或编译器限制。 ```cpp // 声明一个简单的结构体用于示例 struct Point { int x; int y; }; ``` #### 动态分配内存并返回指向结构体数组的指针 当需要从函数返回多个结构体组成的集合时,可以在堆上动态分配这些结构体的空间,并让调用者负责释放这部分资源[^1]。 ```cpp Point* createPointsArray(int size) { // 创建一个新的Point类型的数组 Point *points = (Point*)malloc(size * sizeof(Point)); for (int i = 0; i < size; ++i){ points[i].x = i; points[i].y = i * 2; } return points; } ``` 需要注意的是,上述代码中的`createPointsArray()`会返回一个指向新分配的`Point`数组的指针。由于是在堆上分配的,因此使用者应当记得在不再需要这个数组的时候调用`free()`来回收这块内存,防止发生内存泄漏。 #### 使用静态局部变量 另一种方法是使用带有静态存储持续时间(static storage duration)的局部变量。这种方式下,即使函数执行完毕后,所创建的对象也会一直存在直到程序结束。不过这种方法并不推荐广泛使用,因为它可能会引发难以调试的问题,比如多线程环境下的竞态条件(race condition)[^5]。 ```cpp static Point static_points[10]; Point* getStaticPoints() { // 初始化一些值... for (int i = 0; i < 10; ++i){ static_points[i].x = i; static_points[i].y = i * 2; } return static_points; } ``` #### 利用容器类(仅限于C++) 对于C++而言,还可以考虑使用标准模板库(STL)提供的容器如`std::vector<Point>`来代替原始数组。这不仅简化了管理动态大小序列的任务,而且也避免了许多潜在的风险,例如忘记释放手动分配的内存等问题[^3]。 ```cpp #include<vector> std::vector<Point> generateVectorOfPoints(int count) { std::vector<Point> vec(count); for (size_t i = 0; i < count; ++i){ vec.at(i).x = i; vec.at(i).y = i * 2; } return vec; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值