我知道如何以下列方式执行一个不可能的非连续数组:
int main () {
int ***array = (int***)malloc(3*sizeof(int**));
int i, j;
for (i = 0; i < 3; i++) {
// Assign to array[i], not *array[i] (that would dereference an uninitialized pointer)
array[i] = (int**)malloc(3*sizeof(int*));
for (j = 0; j < 3; j++) {
array[i][j] = (int*)malloc(3*sizeof(int));
}
}
array[1][2][1] = 10;
return 0;
}
使用上面的代码,数组[0] [j]块可能不连续。为了获得连续性,我觉得我们需要以这种方式使用malloc
int* array = (int*)malloc(3*3*3*sizeof(int));
int** y = (int**)malloc(3*3*sizeof(int**));
int*** x = (int***)malloc(3*sizeof(int***));
for(i = 0; i < 3; i++)
{
vals = vals + i*m*n;
x[i] = &vals;
for(j = 0; j < 3; j++)
{
x[i][j] = vals + j * n;
}
}
然而,我遇到了地址分配问题。我不是程序员,任何人都可以纠正我的错吗?提前谢谢......
答案 0 :(得分:1)
int*** x = (int***)malloc(3*sizeof(int***));
应该是
int*** x = (int***)malloc(3*sizeof(int**));
现在初始化可以是:
for(i = 0; i < 3; i++)
{
x[i] = y + 3*i;
for(j = 0; j < 3; j++)
{
x[i][j] = array + i*3*3 + j*3;
}
}
因此x[0]
指向y
的第一个元素,x[1]
指向第四个元素,等等。
并且x[0][0]
= y[0]
到array
的第一个,x[0][1]
= y[1]
到array
的第四个等等。
答案 1 :(得分:1)
要分配连续的 3D数组,您只需执行以下操作(假设所有维度在编译时都已知):
#define D0 ...
#define D1 ...
#define D2 ...
...
T (*arr)[D1][D2] = malloc( sizeof *arr * D0 ); // for any type T
...
arr[i][j][k] = some_value();
...
arr
被声明为指向D1
x D2
数组的指针。然后,我们为D0
这样的数组(sizeof *arr == sizeof (T [D1][D2])
)分配足够的空间。
使用此方法,阵列的所有内存都是连续分配的。此外,您只需要调用free
即可释放整个内容。
如果在运行和之前不知道您的维度,那么您使用的是C99编译器或支持可变长度数组的C2011编译器,那么您仍然很幸运:
size_t d0, d1, d2;
...
T (*arr)[d1][d2] = malloc( sizeof *arr * d0 );
主要问题是如何将此作为参数传递给函数。假设在编译时已知D1
和D2
,如果您决定将其作为
foo( arr, D0 );
然后foo
的原型需要
void foo( T (*aptr)[D1][D2], size_t n )
{
...
aptr[i][j][k] = ...;
}
它仅对 n
x D1
x D2
大小的数组有用。
如果你去VLA路线,你还需要声明尺寸并为它们传递值:
void foo( size_t d0, size_t d1, size_t d2, T (*aptr)[d1][d2] ) // d1 and d2 *must* be
// declared before aptr
{
...
arr[i][j][k] = some_value();
}
void bar( void )
{
size_t d0, d1, d2;
...
T (*arr)[d1][d2] = malloc( sizeof *arr * d0 );
...
foo( d0, d1, d2, arr );
...
}
如果您没有支持VLA的编译器,但仍希望连续分配此内存,那么您必须采用旧式路由 - 将其分配为一维数组并进行计算手动补偿:
T *arr = malloc( sizeof *arr * d0 * d1 * d2 );
...
arr[i * d0 * d1 + j * d1 + k] = some_value();
答案 2 :(得分:0)
我正在使用一些非常简洁的方法来分配带有行指针的多维数组。函数multi_malloc
和multi_free
可用于具有任意维度和任意类型的数组,它们基本上适用于所有平台以及C和C ++
你可以分配,例如一个带有行指针递归的三维数组。例如。一个10x20x30维阵列
float*** data = (float***) multi_malloc(sizeof(float),3, 10,20,20);
访问
等元素data[2][3][4] = 2.0;
并释放所有内容(数据和行指针)
multi_free(data,3);
标题,我认为应该是C的一部分
#pragma once
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#if (defined(_MSC_VER) && defined(_WIN32))
// Note when used inside a namespace, the static is superfluous
# define STATIC_INLINE_BEGIN static inline //__forceinline
# define STATIC_INLINE_END
#elif (defined(__GNUC__))
# define STATIC_INLINE_BEGIN static inline
# if defined(__CYGWIN__)
# define STATIC_INLINE_END
# else
# define STATIC_INLINE_END __attribute__ ((always_inline))
# endif
#endif
STATIC_INLINE_BEGIN void* multi_malloc(size_t s, size_t d, ...) STATIC_INLINE_END;
STATIC_INLINE_BEGIN void multi_free(void *r, size_t d) STATIC_INLINE_END;
/**
* Allocate multi-dimensional array and establish row pointers
*
* @param s size of each element
* @param d number of dimension
*
* @return
*/
STATIC_INLINE_BEGIN void* multi_malloc(size_t s, size_t d, ...) {
char* tree;
va_list ap; /* varargs list traverser */
size_t max, /* size of array to be declared */
*q; /* pointer to dimension list */
char **r, /* pointer to beginning of the array of the
* pointers for a dimension */
**s1, *t; /* base pointer to beginning of first array */
size_t i, j; /* loop counters */
size_t *d1; /* dimension list */
va_start(ap,d);
d1 = (size_t *) malloc(d*sizeof(size_t));
for(i=0;i<d;i++)
d1[i] = va_arg(ap,size_t);
r = &tree;
q = d1; /* first dimension */
if (d==1) {
max = *q;
free(d1);
return malloc(max*d);
}
max = 1;
for (i = 0; i < d - 1; i++, q++) { /* for each of the dimensions
* but the last */
max *= (*q);
r[0]=(char *)malloc(max * sizeof(char **));
r = (char **) r[0]; /* step through to beginning of next
* dimension array */
}
max *= s * (size_t) (*q); /* grab actual array memory */
r[0] = (char *)malloc(max * sizeof(char));
/*
* r is now set to point to the beginning of each array so that we can
* use it to scan down each array rather than having to go across and
* then down
*/
r = (char **) tree; /* back to the beginning of list of arrays */
q = d1; /* back to the first dimension */
max = 1;
for (i = 0; i < d - 2; i++, q++) { /* we deal with the last
* array of pointers later on */
max *= (*q); /* number of elements in this dimension */
for (j=1, s1=r+1, t=r[0]; j<max; j++) { /* scans down array for
* first and subsequent
* elements */
/* modify each of the pointers so that it points to
* the correct position (sub-array) of the next
* dimension array. s1 is the current position in the
* current array. t is the current position in the
* next array. t is incremented before s1 is, but it
* starts off one behind. *(q+1) is the dimension of
* the next array. */
*s1 = (t += sizeof (char **) * *(q + 1));
s1++;
}
r = (char **) r[0]; /* step through to begining of next
* dimension array */
}
max *= (*q); /* max is total number of elements in the
* last pointer array */
/* same as previous loop, but different size factor */
for (j = 1, s1 = r + 1, t = r[0]; j < max; j++)
*s1++ = (t += s * *(q + 1));
va_end(ap);
free(d1);
return((void *)tree); /* return base pointer */
}
/**
* Free multi-dimensional array and corresponding row pointers
*
* @param r data
* @param d number of dimensions
*/
STATIC_INLINE_BEGIN void multi_free(void *r, size_t d) {
void **p;
void *next=NULL;
size_t i;
for (p = (void **)r, i = 0; i < d; p = (void **) next,i++)
if (p != NULL) {
next = *p;
free(p);
p = NULL;
}
}
答案 3 :(得分:0)
虽然我认为在堆栈上创建的普通数组最好:
int array[3][3][3];//can avoid a lot of free() calls later on
这是一种动态创建3D阵列的方法:
(我在这里使用calloc而不是malloc,因为它创建了初始化的内存空间)
int *** Create3D(int p, int c, int r)
{
int ***arr;
int x,y;
arr = calloc(p, sizeof(arr)); //memory for int
for(x = 0; x < p; x++)
{
arr[x] = calloc(c ,sizeof(arr)); //memory for pointers
for(y = 0; y < c; y++)
{
arr[x][y] = calloc(r, sizeof(int));
}
}
return arr;
}
用法 可以是:
int ***array = Create3D(3,3,3);
for(i=0;i<3;i++)
for(j=0;j<3;j++)
for(k=0;k<3;k++)
array[i][j][k] = (i+1)*(j+1)*(k+1);
请注意,在此示例中不会返回[c] [m] [re] alloc()的返回值。虽然在C中没有严格禁止,但不建议使用。 (在C ++中不是这种情况, 是必需的)
请记住 ,必须释放所有已分配的内容。注意释放是按照分配的相反顺序完成的:
void free3D(int ***arr, int p, int c)
{
int i,j;
for(i=0;i<p;i++)
{
for(j=0;j<c;j++)
{
if(arr[i][j]) free(arr[i][j]);
}
if(arr[i]) free(arr[i]);
}
if(arr) free(arr);
}
用法 可以是:
free3D(array,3,3);
答案 4 :(得分:0)
您可以为每个项目是二维数组的项目缓冲区分配内存。所以它实际上是一个三维数组:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 3
int main()
{
int (*array)[N][N] = malloc(N * N * N * sizeof(int));
/* set 0 to all values */
memset(array, 0, N * N * N * sizeof(int));
/* use as 3D array */
array[0][0][0] = 1;
array[1][1][1] = 2;
array[2][2][2] = 3;
int i;
/* print array as contiguous buffer */
for (i = 0; i < N * N * N; ++i)
printf("i: %d\n", ((int*) array)[i]);
free(array);
return 0;
}
因此,在内存中array
被定位为常规int array[N][N][N]
。