在C/C++中动态分配二维数组可以先申请一维的指针数组,然后该数组中的每个指针再申请数组,这样就相当于二维数组了,但是这种方法会导致每行可能不相邻,从而访问效率比较低。如何申请连续的二维数组了?本文将分别三个方面讲解:
一.动态申请列大小固定的二维数组
二.C语言中动态申请连续的二维数组
三.C++语言中动态申请连续的二维数组
一.动态申请列大小固定的二维数组
首先如果二维数组的列大小固定,那么很简单,可以用申请一维数数组再其指针强制转化成为二维数组指针即可。详见代码:
//列大小固定的二维数组可以申请一维数据并将指针强转成二维数组
#include <stdio.h>
int main()
{
printf(" 列大小固定的二维数组可以申请一维数据并将指针强转成二维数组\n");
printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");
//列值固定
const int MAXCOL = 3;
int nRow;
printf("请输入二维数组的行数(列值固定为%d): ", MAXCOL);
scanf("%d", &nRow);
//申请一维数据并将其转成二维数组指针
int *pp_arr = new int[nRow * MAXCOL];
int (*p)[MAXCOL] = (int(*)[MAXCOL])pp_arr;
//为二维数组赋值
int i, j;
for (i = 0; i < nRow; i++)
for (j = 0; j < MAXCOL; j++)
p[i][j] = i + j;
//输出二维数组
for (i = 0; i < nRow; i++)
{
for (j = 0; j < MAXCOL; j++)
printf("%5d", p[i][j]);
putchar('\n');
}
//释放资源
delete[] pp_arr;
return 0;
}
运行结果如下所示:
二.C语言中动态申请连续的二维数组
上面的方法虽然方便,但必须要求列的大小固定。下面先来试下在C语言中如何动态申请连续的二维数组。可以采用多申请一些指针,然后这一些指针分别指向后面数据区中对应的位置,如一个3*4的int类型数组,我们先申请大小为sizeof(int*) * 3 + 3 * 4 * sizeof(int)的一维数组设为arr。然后arr[0]存放指向arr + sizeof(int*) * 3这个位置的指针,arr[1]存放指向arr + sizeof(int*) * 3 + 4 * sizeof(int)这个位置的指针, arr[2]存放指向arr + sizeof(int*) * 3 + 2 * 4 * sizeof(int)这个位置的指针。下面用图展示指向的示意:
详细代码如下,由于指针操作有点小复杂,请读者耐心看:
//C语言中动态的申请二维数组 malloc free
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//动态申请二维数组
template <typename T>
T** malloc_Array2D(int row, int col)
{
int size = sizeof(T);
int point_size = sizeof(T*);
//先申请内存,其中point_size * row表示存放row个行指针
T **arr = (T **) malloc(point_size * row + size * row * col);
if (arr != NULL)
{
memset(arr, 0, point_size * row + size * row * col);
T *head = (T*)((int)arr + point_size * row);
while (row--)
arr[row] = (T*)((int)head + row * col * size);
}
return (T**)arr;
}
//释放二维数组
void free_Aarray2D(void **arr)
{
if (arr != NULL)
free(arr);
}
int main()
{
printf(" C语言中动态的申请二维数组 malloc free\n");
printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");
printf("请输入行列(以空格分开): ");
int nRow, nCol;
scanf("%d %d", &nRow, &nCol);
//动态申请连续的二维数组
int **p = malloc_Array2D<int>(nRow, nCol);
//为二维数组赋值
int i, j;
for (i = 0; i < nRow; i++)
for (j = 0; j < nCol; j++)
p[i][j] = i + j;
//输出二维数组
for (i = 0; i < nRow; i++)
{
for (j = 0; j < nCol; j++)
printf("%4d ", p[i][j]);
putchar('\n');
}
free_Aarray2D((void**)p);
return 0;
}
运行结果如下:
三.C++语言中动态申请连续的二维数组
可以看出我们已经成功实现了在C语言中动态申请连续的二维数组,如果上面的程序不使用int类型而使用string类这种类型,那会有什么后果了?肯定的说,由于没有调用构造函数和析构函数,程序绝对会造成内存泄露。因此要做下改进,下面给出在C++语言中动态申请连续的二维数组的代码,有些C++语法可能平时见得少,但其实这些语法在STL里面运用还是比较多的,有兴趣的童鞋应该掌握下。
//C++语言中动态的申请二维数组 new delete
#include <new>
#include <cstdio>
#include <cstdlib>
#include <string>
using namespace std;
//动态申请二维数组
template <typename T>
T** new_Array2D(int row, int col)
{
int size = sizeof(T);
int point_size = sizeof(T*);
//先申请内存,其中sizeof(T*) * row表示存放row个行指针
T **arr = (T **) malloc(point_size * row + size * row * col);
if (arr != NULL)
{
T *head = (T*)((int)arr + point_size * row);
for (int i = 0; i < row; ++i)
{
arr[i] = (T*)((int)head + i * col * size);
for (int j = 0; j < col; ++j)
new (&arr[i][j]) T;
}
}
return (T**)arr;
}
//释放二维数组
template <typename T>
void delete_Array2D(T **arr, int row, int col)
{
for (int i = 0; i < row; ++i)
for (int j = 0; j < col; ++j)
arr[i][j].~T();
if (arr != NULL)
free((void**)arr);
}
int main()
{
printf(" C++语言中动态的申请二维数组 new delete\n");
printf(" -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");
printf("请输入行列(以空格分开): ");
int nRow, nCol;
scanf("%d %d", &nRow, &nCol);
//动态申请连续的二维数组
string **p = new_Array2D<string>(nRow, nCol);
//为二维数组赋值
int i, j;
for (i = 0; i < nRow; i++)
for (j = 0; j < nCol; j++)
{
char szTemp[30];
sprintf(szTemp, "(第%d行,第%d列)", i, j);
p[i][j] = szTemp;
}
//输出二维数组
for (i = 0; i < nRow; i++)
{
for (j = 0; j < nCol; j++)
printf("%s ", p[i][j].c_str());
putchar('\n');
}
delete_Array2D<string>(p, nRow, nCol);
return 0;
}
运行结果如下:
分享到:
相关推荐
在C/C++编程中,二维指针是一种强大的工具,它被用来表示多维数组或矩阵。二维指针的使用涉及到动态内存分配、数组操作以及内存管理等核心概念。本篇文章将详细探讨这些知识点,并结合提供的链接(由于此处无法直接...
虽然Java语言并没有提供真正意义上的多维数组(如C/C++中的那样),但通过嵌套使用一维数组的方式可以实现类似的功能。 #### 二、二维数组的基本语法 1. **声明二维数组**: - 声明一个二维数组的基本格式为:`...
【C/C++笔试题解析】 在C/C++的笔试题中,常见的问题涵盖了语言的各个方面,包括基础语法、数据结构、算法以及特定概念的理解。以下是对一些常见知识点的详细解释: 1. **位操作**: - 题目1中的`func(x)`函数...
从给定的文件信息中,我们可以总结出一系列关于C/C++编程语言的重要知识点,特别是针对笔试和面试场景下的常见问题。以下是对标题、描述、标签和部分内容中提及的知识点的详细解析: ### 1. 函数返回值计算 在微软...
在C/C++编程中,内存管理是至关重要的概念,尤其是对于面试来说,了解new、delete、malloc和free的关系以及它们的正确使用方式是基础。new和delete是C++中的运算符,负责对象的动态内存分配和释放,同时处理对象的...
### C/C++笔试面试题目大汇总 #### 1. 求下面函数的返回值(微软) 函数示例代码如下: ```c++ int func(int x) { int count_x = 0; while (x) { count_x++; x = x & (x - 1); } return count_x; } ``` ...
在C/C++编程中,面试题常常涉及到语言的核心概念,如指针、引用以及函数参数传递等。以下是对这些知识点的详细解释: 1. **位操作函数**:题目中的`func(x)`函数通过位操作计算整数x中二进制表示下的1的个数。这种...
《C&C++笔试题大全》一书主要涵盖了C和C++编程语言的各类笔试题目,旨在帮助应聘者准备C++程序员和软件开发等职位的面试。以下是对书中的部分知识点的详细解释: 1. **位操作函数分析**: - `func` 函数通过位操作...
在IT行业的面试和笔试中,C++语言的相关知识是经常被考察的重点。以下是一些关于C++的关键知识点,包括函数、引用以及它们在面试和笔试中的应用。 1. **位操作函数**: - `func(x)` 函数通过位操作计算整数 `x` ...
从给定的文件信息中,我们可以提炼出一系列与C/C++相关的知识点,涵盖函数解析、引用的概念、引用作为函数参数的特性、常引用的应用场景以及引用作为函数返回值的格式与规则。以下是对这些知识点的详细说明: ### ...
2012-06-11 08:52 190,100 C++中二维数组与指针关系的剖析.pdf 2012-06-11 08:48 171,862 C++函数后加const的意义.pdf 2012-06-11 08:57 9,174 C++注册表操作大全.txt 2012-06-11 08:37 113,664 CCheckListBox和...
《C C++ 笔试题集锦(找工作面试必读)》 C 和 C++ 是两种广泛应用的编程语言,尤其在系统编程和底层开发领域。掌握它们的基础知识和深入概念是找工作面试的重要准备。以下是一些关于 C/C++ 笔试题目和相关知识点的...
`malloc`和`free`是C/C++标准库函数,而`new`和`delete`是C++特有的运算符。`new`不仅分配内存,还会调用构造函数初始化对象,而`delete`则负责调用析构函数清理资源。由于`malloc`和`free`不具备这样的功能,它们...
1. **内存管理**:在C++中,`new`和`delete`是用于动态内存分配和释放的运算符,它们对应于C语言中的`malloc`和`free`。`new`会调用对象的构造函数,而`delete`会调用析构函数。`malloc`和`free`仅负责内存的分配和...
- **malloc** 和 **free** 是C/C++标准库函数,用于动态内存的分配和释放。 - `malloc` 分配内存但不会调用构造函数。 - `free` 释放内存但不会调用析构函数。 对于非内置数据类型的对象,仅使用 `malloc` 和 `...
《C、C++笔试题集锦》文档涵盖了多个C++编程中的关键概念,特别是关于“引用”的深入讨论。引用在C++中是一个重要的特性,它提供了另一种方式来处理变量,类似于指针,但又有所不同。 1. 题目1考察了位操作。`func...
C 和 C++ 面试笔试题中涵盖了各种核心概念,包括函数、引用、常引用以及函数参数和返回值的处理。以下是对这些知识点的详细解释: 1. **位操作函数**: 函数 `func(x)` 使用了位操作来计算整数 `x` 中二进制表示中...
- **数组引用**:不能声明数组的引用,因为数组本身就是一个固定大小的实体,不能通过引用改变其大小。 #### 3. 引用作为函数参数的特点 - **传递机制**:与指针相似,引用传递避免了复制参数的开销,提高了函数...
在C++编程语言中,笔试题集锦通常涵盖了一系列核心概念和技术,旨在测试候选人的编程能力。以下是针对题目中提及的一些关键知识点的详细解释: 1. **位操作**: - `func(x)` 函数通过位操作计算整数x中二进制表示...
String类通常用于封装C风格的字符数组,提供更安全和方便的字符串操作。给出的实现包含了构造函数、拷贝构造函数、赋值运算符重载和析构函数。构造函数根据输入的字符串动态分配内存,并复制字符串内容。拷贝构造...