C/C++中的二维指针问题

本文深入探讨了一维与二维指针的区别及应用场景,特别是在图像处理中的优势。通过对比三种不同的二维指针定义,详细分析了各自的内存分配、使用方法及其特点。

本文参考网络资源,对其进行了整理。

http://www.wangchao.net.cn/bbsdetail_59038.html

http://blog.youkuaiyun.com/jia_xiaoxin/archive/2008/11/10/3268645.aspx

 

      指针是可变数组的首地址。正因为是可变数组,所以一般使用指针时都是采用动态内存分配和释放的方式。一维指针形式简单,容易理解。平时应用较多。二维数组和二维指针比较复杂,并且在动态内存分配与释放方面比较复杂且难以理解。但是二维数组和二维指针是非常有用的。

     考虑以下应用:对一幅图像进行模板运算。这必然会牵涉到对图像的各象素点的操作。此时使用一维指针进行图像传递时,不可避免的会使用形如*(p+i*width+j)的方式完成对图像象素点的访问。这种方式很不直观并且编写程序时容易出错。如果使用二维指针进行图像数据的传递,则会收到很好的效果。可以采用p[i][j]的方式直接操作象素点,直观又便于维护。因此掌握二维数组和二维指针是必要的。

使用http://www.wangchao.net.cn/bbsdetail_59038.html中的示例。

定义如下3个二维数组和二维指针进行说明:

1.         int** ptr;

2.         int *ptr[M];

3.         int (*ptr)[M];

以上都是存放整数的二维数组,并且都可以通过ptr[i][j]的形式访问内容。但是它们之间有很大的差别。以下依照文中提到的方面进行分析。

l         内容
三个ptr本身都是指针,并且是二维指针,但是它们的最终内容总是整数。但中间内容,形如ptr[i]并不是整数,而是指针int *.

l         意义
1. int** ptr 表示指向(一组指向整数数据指针)的指针;
2. int *ptr[M] 是指针数组,表示指向(M个指向整数指针)的指针;
3. int (*ptr)[M]表示指向一组(指向包含M个整型数据的指针)的指针。

l         所占空间
13占用一个内存空间,在32位平台上为4个字节,也就是一个指针。
2M个指针,在其定义过程中编译器即对其进行了分配,占用4*M4M个字节。

l         用法
1. int** ptr 表示指向(一组指向整数数据指针)的指针,是一个二维指针。在其定义过程中,编译器并不对其进行内存的分配,因此必须自己管理其内存的分配与释放。典型使用如下:

    
使用上述方法分配内存,最终ptr耗费的内存空间为M*sizeof(int*)+M*N*sizeof(int)

2. int *ptr[M]
是指针数组,表示指向(M个指向整数指针)的指针。是一个二维指针。但是在定义的时候,编译器已经为ptr指向的M个指向整数的指针ptr[0:M-1]分配了内存。也就是说,定义之后即可得到ptr的地址以及用于存放ptr[0:M-1]的内存空间4MB。要使用ptr必须对ptr[i]分配内存。分配内存后,ptr地址相应内存空间填入ptr[i]指向内存地址。使用如下操作:


使用上述方法分配内存,最终ptr耗费的内存空间为M*sizeof(int*)+M*N*sizeof(int),其中M*sizeof(int*)为编译器分配,M*N*sizeof(int)为程序员自己分配。

3. int (*ptr)[M]表示指向一组(指向包含M个整型数据的指针)的指针。该定义限定了ptr[i][0:M-1],所有指针ptr[i]必须指向长度为M的数组。使用方式如下:
  
使用上述方法分配内存后,ptr所占内存空间为M*N*sizeof(int)(不考虑不同操作系统用于管理的内存)。ptr内存空间中保存的为最终内容而非ptr[i]地址。

    

         最后回到开始考虑的应用,使用以下解决方案:

        

### C/C++二维指针的使用方法 #### 定义与声明 在 C 和 C++ 中,可以定义指向一维数组的指针来模拟多维数组的行为。对于二维指针而言,通常是指向指针类型的指针变量。这种结构允许动态分配内存并创建更灵活的数据存储方式。 ```cpp // 声明一个整型的双层间接寻址符(即指向指针) int **ptr; ``` 为了使 `ptr` 能够访问实际数据,在使用前还需要对其进行适当初始化[^1]。 #### 动态分配空间 当处理大小未知直到运行时才能确定的情况时,可以通过如下方式进行动态分配: ```cpp const int rows = 3, cols = 4; // 分配行数个指针的空间 ptr = new int*[rows]; for(int i = 0; i < rows; ++i){ // 对每一行分配列数个整数的空间 ptr[i] = new int[cols]; } ``` 这段代码展示了如何为每行列分别开辟独立区域,并让顶层指针指向这些子集中的第一个元素位置[^2]。 #### 初始化与赋值操作 一旦有了足够的连续或离散区块用于保存数值,则可以直接通过索引来设置具体项的内容: ```cpp int value = 1; for(int row = 0; row < rows; ++row){ for(int col = 0; col < cols; ++col){ ptr[row][col] = value++; } } // 或者采用另一种形式表达相同逻辑: value = 1; for(int row = 0; row < rows; ++row){ for(int col = 0; col < cols; ++col){ *(*(ptr + row) + col) = value++; } } ``` 这里既可以用直观的方式指定坐标点上的新值,也能借助偏移量完成同样的任务[^3]。 #### 访问元素 读取已存入的信息同样简单直接: ```cpp cout << "Matrix elements are:" << endl; for(int row = 0; row < rows; ++row){ for(int col = 0; col < cols; ++col){ cout << ptr[row][col] << "\t"; } cout << endl; } ``` 上述片段会遍历整个矩阵并将各单元格内的数字打印出来。 #### 清理资源 最后不要忘记释放之前请求过的堆区部分以免造成泄漏问题: ```cpp for(int i = 0; i < rows; ++i){ delete[] ptr[i]; // 删除各行所占有的那片区间 } delete[] ptr; // 销毁最外层管理着其他所有者的对象本身 ``` 这一步骤非常重要,因为未妥善回收不再使用的内存可能会给程序带来潜在风险。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值