这个问题的目的是提供一个关于如何在C中动态正确分配多维数组的参考.这是一个经常被误解的主题,即使在一些C编程书籍中也很难解释.因此,即使是经验丰富的C程序员也很难做到正确.
我从编程教师/书籍/教程中了解到,动态分配多维数组的正确方法是使用指针指针.
然而,SO上的几个高代表用户现在告诉我这是错误和不好的做法.他们说指针到指针不是数组,我实际上并没有分配数组,而且我的代码不必要地慢.
这就是我教我分配多维数组的方法:
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
int** arr_alloc (size_t x, size_t y)
{
int** pp = malloc(sizeof(*pp) * x);
assert(pp != NULL);
for(size_t i=0; i<x; i++)
{
pp[i] = malloc(sizeof(**pp) * y);
assert(pp[i] != NULL);
}
return pp;
}
int** arr_fill (int** pp, size_t x, size_t y)
{
for(size_t i=0; i<x; i++)
{
for(size_t j=0; j<y; j++)
{
pp[i][j] = (int)j + 1;
}
}
return pp;
}
void arr_print (int** pp, size_t x, size_t y) …Run Code Online (Sandbox Code Playgroud) c arrays dynamic-arrays dynamic-allocation variable-length-array
您认为关于2D阵列的内存映射的讨论是正确的吗?特别是这张照片?你能解释一下这个理论吗?
假设我们在C中声明一个2D数组,如下所示:
int arr[3][3]={10, 20, 30, 40, 50, 60, 70, 80, 90};
Run Code Online (Sandbox Code Playgroud)
现在,根据这个讨论,内存将按如下方式排列:

现在,我编写了以下代码来测试这个理论:
#include <stdio.h>
main()
{
int arr[3][3]={10, 20, 30, 40, 50, 60, 70, 80, 90};
printf(" arr==%d\n", arr);
printf(" &arr[0]==%d\n", &arr[0]);
printf(" arr[0]==%d\n", arr[0]);
printf("&arr[0][0]=%d\n", &arr[0][0]);
printf(" arr[0][0]=%d\n", arr[0][0]);
}
/*
Output:
========
arr ==1245028
&arr[0] ==1245028
arr[0] ==1245028
&arr[0][0]==1245028
arr[0][0]==10
Press any key to continue...
*/
Run Code Online (Sandbox Code Playgroud)
为什么前4个输出相同?
我有一个关于如何分配内存的问题calloc.我看了一下这个问题,但它没有解决在动态分配二维数组的情况下如何分配内存的问题.
我想知道以下三种动态分配2D数组的方式之间的内存表示是否存在差异.
类型1:
double **array1;
int ii;
array1 = calloc(10, sizeof(double *));
for(ii = 0; ii < 10; ii++) {
array1[ii] = calloc(10, sizeof(double));
}
// Then access array elements like array1[ii][jj]
Run Code Online (Sandbox Code Playgroud)
类型2:
double **array1;
int ii;
array1 = calloc(10 * 10, sizeof(double *));
// Then access array elements like array1[ii + 10*jj]
Run Code Online (Sandbox Code Playgroud)
类型3:
double **array1;
int ii;
array1 = malloc(10 * 10, sizeof(double *));
// Then access array elements like array1[ii + 10*jj]
Run Code Online (Sandbox Code Playgroud)
从我所理解的calloc …
我经常需要在编译时创建一个宽度和高度(让它们是n和m)未知的2D数组,通常我会写:
vector<int> arr(n * m);
Run Code Online (Sandbox Code Playgroud)
我手动访问元素:
arr[j * m + i]
Run Code Online (Sandbox Code Playgroud)
我最近被告知我可以改为写:
int arr[n][m] // n and m still only known at runtime.
Run Code Online (Sandbox Code Playgroud)
所以这里有两个问题:
int (*)[n],但同样,n是动态的,并且在声明它的函数之外不知道(main).我正在为我正在参加的C编程课程做实验工作.我在我的本地Cygwin目录中编写了代码gcc,并使用它编译,并且生成的可执行文件完全按照我希望的方式工作而没有任何错误.
当我将代码复制到学校的UNIX服务器并使用它编译时gcc,我没有收到任何错误,但是当我尝试运行它时,没有任何反应.
我试过了gcc 2darray.c -Wall -pedantic,这就是返回的内容:
2darray.c: In function 'main':
2darray.c:5:3: warning: missing braces around initializer [-Wmissing-braces]
2darray.c:5:3: warning: (near initialization for 'M[0]') [-Wmissing-braces]
2darray.c:5:24: warning: C++ style comments are not allowed in ISO C90 [enabled by default]
2darray.c:5:24: warning: (this will be reported only once per input file) [enabled by default]
Run Code Online (Sandbox Code Playgroud)
这些错误提到了初始化数组的一些问题M,但我没有看到初始化它的方式有任何问题.这是我正在尝试编译的代码:
#include <stdio.h>
int main(void)
{
int M[10][10] = {0}; // creating a 10x10 array and initializing it to 0 …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用打印2D矩阵[],而不是*像指针一样使用.
因此,对于1 D阵列,我会这样做:*(arr+i)例如.用于替换的语法是matrix[][]什么?
这是代码:
for (i = 0; i < size; i++)
{
for (j = 0; j < (size * 2); j++)
{
printf(" %5d", matrix[i][j]);
}
printf("\n");
}
Run Code Online (Sandbox Code Playgroud)
PS,我确实尝试了几件事:
*(matrix+i+j);
*(matrix+i)+*(matrix+j);
Run Code Online (Sandbox Code Playgroud)
当然没有一个有效.
谢谢你的帮助和时间!
所以在我正在做的每次迭代结束时,我想让我的数组等于我的新数组(我称之为array_new).我希望数组的每个元素都采用与array_new相同的值,但我有兴趣尽可能快地获取代码,因此在当前代码执行的情况下,逐个元素地复制所有元素不是一个选项:
for(i=0;i<N_a;i++) {
for(j=0;j<N_b;j++) {
array[i][j] = array_new[i][j];
}
}
Run Code Online (Sandbox Code Playgroud)
这需要相当长的时间,因为我的N_a和N_b的值非常大.有没有办法简单地改变每个指向的内容,以便我可以更快地开始下一次迭代?我尝试过这样的事情
double *temp = *array;
*array = *array_new;
*array_new = temp;
Run Code Online (Sandbox Code Playgroud)
为了尝试避免缓慢的逐个元素复制过程,但它似乎不适合我.实际上,我正在努力实现的是,数组的每个元素都指向array_new中的相应元素,但我无法弄清楚如何使指针执行此操作.
任何帮助将非常感激!
我知道这个答案违反了reinterpret_cast规则,但它也假设子阵列将被线性分配.
我相信这不能保证,但是当我搜索标准时,我发现我的信心摇摆不定.如果我静态分配2D数组,如下所示:
int foo[][4] = { { 5, 7, 8 },
{ 6, 6 },
{},
{ 5, 6, 8, 9 } };
Run Code Online (Sandbox Code Playgroud)
我可以假设所有元素都将线性分配吗?也就是说,如果foo[0]是在地址0x00000042,将:
foo[1] 在地址0x00000052foo[2] 在地址0x00000062foo[3] 在地址0x00000072这些地址是十六进制的,是的,它们为4元素子阵列提供了空间sizeof(int) == 4; 它们可能也可能不是零初始化.
我想通过遍历一个for循环来填充数组。
假设我有:
int8 myArray[30] = {0}; // Declaring and initializing an array which contains maximum 30 elements
Run Code Online (Sandbox Code Playgroud)
在for循环中向数组添加元素:
for (i = 0; i<5; i++)
{
myArray[0+(i*5)] = getNumberfromFunction1();
myArray[1+(i*5)] = getNumberfromFunction2();
myArray[2+(i*5)] = getNumberfromFunction3();
myArray[3+(i*5)] = getNumberfromFunction4();
myArray[4+(i*5)] = getNumberfromFunction5();
myArray[5+(i*5)] = getNumberfromFunction6();
}
Run Code Online (Sandbox Code Playgroud)
循环的每个元素应按以下方式填充:
myArray [0] = getNumberfromFunction1();
myArray [1] = getNumberFromFunction2();
...
...
myArray [5] = getNumberFromFunction6();
myArray [6] = getNumberFromFunction1();
....
....
i = 0的第一圈,索引正确:
myArray[0] = ..
myArray[1] = ..
..
..
myArray[5] = ..
Run Code Online (Sandbox Code Playgroud)
当i …
我正在尝试以下代码用于多维数组.它给出SEG错误我不知道这是什么问题.
static void read(double **arr){
//REQ arr to be pointing to array[5][4]
//EFF prompt the use to input the data
//Mod array pointer by **arr
int i(0) , j(0);
double tmp ;
for(i=0 ; i<4 ; i++){
for(j=0 ; j<5 ; j++) {
cout <<"Please enter Data#"<< (j+1) << " File#" << (i+1) <<" "<<flush;
cin >> tmp ;
arr[j][i] = tmp ;
}
}
return ;
}
int main(){
double arr[5][4] ;
read(reinterpret_cast<double**>(arr) ) ;
}
Run Code Online (Sandbox Code Playgroud)
我在这做错了什么?
我对增加数组的指针然后测量指针位置的字节差异感到困惑.
我知道*p当通过多维数组移动时,指针将按数据类型的大小递增.但是,当使用数组时thisArray:
int thisArray[ 7 ][ 4 ];
Run Code Online (Sandbox Code Playgroud)
应该如何thisArrray + 1评估?我是否增加行和列?
我想知道这些指针将在内存中分开多少个字节.
我知道确切的答案将取决于平台.我正在寻求解决方法,而不是确切的答案.
由于我无法在评论中格式化代码:我将它放在这里:
//使用sizeof
#include <stdio.h>
int main(void) {
int tbl[ 7 ][ 4 ];
// Size of tbl
int x = sizeof(*tbl);
printf ( "%d\n" , x);
// Size of tbl + 1;
int y = sizeof(*tbl+1);
printf( "%d\n", y);
//Size apart in bytes
int z = y - x;
printf("%d\n", z);
return 0;
}
Run Code Online (Sandbox Code Playgroud) 有什么区别
#include <stdio.h>
int a[9];
int
main()
{
printf("%d\n", a[1]);
}
Run Code Online (Sandbox Code Playgroud)
和
#include <stdio.h>
int a[3][3];
int
main()
{
printf("%d\n", a[1]);
}
Run Code Online (Sandbox Code Playgroud)
我认为两者都会在.bss段中放置相同的36字节内存缓冲区,有什么区别?或者a[3][3]语法糖结束了a[9] - a[3*3]吗?
c ×9
arrays ×7
pointers ×4
c++ ×3
calloc ×1
for-loop ×1
gcc ×1
malloc ×1
optimization ×1
syntax-error ×1