如您所知,在 C 中,没有二维数组。只有模拟二维数组索引的方法。它们分为两类,(1)创建一个指向数组的指针数组,以及(2)创建一个正常的顺序数组并使用索引算法以二维方式引用元素。在每种情况下,可以根据数组中的元素总数(或数组的size)和要模拟的数组的列数(或stride)来考虑算术。知道数组的size 和stride,通过仔细的索引,您可以将C - 1D 数组用作2D 数组。为了帮助解决与这两种类型以及指针和索引的使用有关的任何问题,请考虑以下事项:
要输入的指针数组
首先,当您使用 指向类型的指针数组(例如 int **array)时,您分配 ROWS 指向 COLS 大小的类型数组(本质上是 @987654328 @ number of COLS 大小的数组。)然后通过取消引用,您可以将元素索引为 2D 数组(例如 array[0][x] 其中 0 <= x < COLS 读取第一个指针 array[1][x] 指向的数组中的所有内容,第二个指针,等等……)。
要将指针数组分配给类型,请分配ROWS 的指针数量(其中ROWS 等效于size/stride):
int **array = NULL;
...
array = xcalloc (size/stride, sizeof *array);
(注意: xcalloc 只是一个使用 calloc 并带有错误检查来验证分配的函数)
分配ROWS 的指针数量后,您为每个原始指针分配一个单独的包含COLS(或stride)元素的列数组。
for (i = 0; i < size/stride; i++)
array[i] = xcalloc (stride, sizeof **array);
分配指针数组后,您将使用两个循环来填充/操作数组中的数据:
for (i = 0; i < size/stride; i++)
for (j = 0; j < stride; j++)
array[i][j] = rand() % 1000;
您可以使用简单的array[i][j] 语法访问任何单个成员。请记住,您只需将size/stride 视为您的ROWS,将stride 视为您的COLS,因此如果您正在计算ROWS 和COLS 的值,您可以将以上内容写为:
for (i = 0; i < ROWS; i++)
for (j = 0; j < COLS; j++)
array[i][j] = rand() % 1000;
将线性阵列视为二维阵列
由于在这种情况下您使用传统的顺序一维数组来保存数据,因此声明和分配数组很简单:
int *array = NULL;
...
array = xcalloc (size, sizeof *array);
注意:要以模拟 2D 方式访问数组的元素,您必须使用与访问值相同的逻辑将值存储在数组中,从循环的角度来看将与您在上面的指向数组的情况下所做的完全相同。唯一的区别是索引的计算:
for (i = 0; i < size/stride; i++)
for (j = 0; j < stride; j++)
array[i * stride + j] = rand() % 1000;
在这里,需要仔细看看您是如何模拟 array[i][j] 访问的。注意:数组的索引:
array[i * stride + j] = rand() % 1000;
当您有一个线性一维数组元素时,允许您以二维方式处理和访问值的索引由array[i * stride + j] 给出,其中i 和j 代表ROWS 和COLS。
将所有这些放在几个示例中,将向您展示所有部分如何组合在一起:
示例 - 要键入的指针数组
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void *xcalloc (size_t n, size_t s);
int main (int argc, char **argv) {
int **array = NULL;
int size = argc > 1 ? (int)strtol(argv[1], NULL, 10) : 36;
int stride = argc > 2 ? (int)strtol(argv[2], NULL, 10) : 6;
int i,j;
/* test valid size/stride */
if (size < stride || size % stride) {
fprintf (stderr, "error: invalid stride '%d' for %d element array.\n",
stride, size);
return 1;
}
srand (time(NULL)); /* initialize seed */
/* alloc array of pointers to array of integers in memory */
array = xcalloc (size/stride, sizeof *array);
/* allocate arrays of integers */
for (i = 0; i < size/stride; i++)
array[i] = xcalloc (stride, sizeof **array);
/* fill with random values */
for (i = 0; i < size/stride; i++)
for (j = 0; j < stride; j++)
array[i][j] = rand() % 1000;
/* printing in simulated 2D format */
printf ("\n printing (%d x %d) array\n\n",
size/stride, stride);
for (i = 0; i < size/stride; i++) {
for (j = 0; j < stride; j++)
printf (" %4d", array[i][j]);
putchar ('\n');
}
/* print a particular element array[1][2] */
if (stride > 1)
printf ("\n array[1][1] in (%d x %d) array : %d\n\n",
size/stride, stride, array[1][1]);
/* free allocated memory */
for (i = 0; i < size/stride; i++)
free (array[i]);
free (array);
return 0;
}
/** xcalloc allocates memory using calloc and validates the return.
* xcalloc allocates memory and reports an error if the value is
* null, returning a memory address only if the value is nonzero
* freeing the caller of validating within the body of code.
*/
void *xcalloc (size_t n, size_t s)
{
register void *memptr = calloc (n, s);
if (memptr == 0)
{
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
return memptr;
}
使用/输出示例
$ ./bin/array_stride_2d 12 2
printing (6 x 2) array
535 68
45 815
348 480
417 151
443 789
267 738
array[1][1] in (6 x 2) array : 815
$ ./bin/array_stride_2d 12 3
printing (4 x 3) array
841 195 147
870 18 892
624 516 820
250 769 532
array[1][1] in (4 x 3) array : 18
$ ./bin/array_stride_2d 12 4
printing (3 x 4) array
116 275 740 510
625 122 386 623
624 879 970 396
array[1][1] in (3 x 4) array : 122
$ ./bin/array_stride_2d 12 6
printing (2 x 6) array
543 631 562 504 307 940
932 75 225 662 181 990
array[1][1] in (2 x 6) array : 75
示例 - 将线性数组视为二维数组
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void *xcalloc (size_t n, size_t s);
int main (int argc, char **argv) {
int *array = NULL;
int size = argc > 1 ? (int)strtol(argv[1], NULL, 10) : 36;
int stride = argc > 2 ? (int)strtol(argv[2], NULL, 10) : 6;
int i,j;
/* test valid size/stride */
if (size < stride || size % stride) {
fprintf (stderr, "error: invalid stride '%d' for %d element array.\n",
stride, size);
return 1;
}
srand (time(NULL)); /* initialize seed */
/* alloc array of size sequential in memory */
array = xcalloc (size, sizeof *array);
/* fill with random values */
for (i = 0; i < size/stride; i++)
for (j = 0; j < stride; j++)
array[i * stride + j] = rand() % 1000;
/* printing in simulated 2D format */
printf ("\n printing (%d x %d) array\n\n",
size/stride, stride);
for (i = 0; i < size/stride; i++) {
for (j = 0; j < stride; j++)
printf (" %4d", array[i * stride + j]);
putchar ('\n');
}
/* print a particular element array[1][2] */
if (stride > 1)
printf ("\n array[1][1] in (%d x %d) array : %d\n\n",
size/stride, stride, array[1 * stride + 1]);
free (array);
return 0;
}
/** xcalloc allocates memory using calloc and validates the return.
* xcalloc allocates memory and reports an error if the value is
* null, returning a memory address only if the value is nonzero
* freeing the caller of validating within the body of code.
*/
void *xcalloc (size_t n, size_t s)
{
register void *memptr = calloc (n, s);
if (memptr == 0)
{
fprintf (stderr, "%s() error: virtual memory exhausted.\n", __func__);
exit (EXIT_FAILURE);
}
return memptr;
}
使用/输出
$ ./bin/array_stride_1d 12 2
printing (6 x 2) array
220 155
755 51
427 270
691 597
982 995
4 444
array[1][1] in (6 x 2) array : 51
$ ./bin/array_stride_1d 12 3
printing (4 x 3) array
990 837 473
153 10 337
139 940 444
768 625 457
array[1][1] in (4 x 3) array : 10
$ ./bin/array_stride_1d 12 4
printing (3 x 4) array
617 943 444 396
38 357 103 441
646 416 40 586
array[1][1] in (3 x 4) array : 357
$ ./bin/array_stride_1d 12 6
printing (2 x 6) array
364 61 373 723 994 849
793 332 913 991 999 373
array[1][1] in (2 x 6) array : 332
内存错误检查
$ valgrind ./bin/array_stride_1d 12 6
==21560== Memcheck, a memory error detector
==21560== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==21560== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==21560== Command: ./bin/array_stride_1d 12 6
==21560==
printing (2 x 6) array
359 841 728 356 563 487
626 58 823 270 860 896
array[1][1] in (2 x 6) array : 58
==21560==
==21560== HEAP SUMMARY:
==21560== in use at exit: 0 bytes in 0 blocks
==21560== total heap usage: 1 allocs, 1 frees, 48 bytes allocated
==21560==
==21560== All heap blocks were freed -- no leaks are possible
==21560==
==21560== For counts of detected and suppressed errors, rerun with: -v
==21560== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
希望这有助于您了解在 C 中基本上有两种将数组视为二维数组的方案。您甚至可以更有创意并创建远远超出 2D 的维度数组,只需注意索引计算很快就会变得更多涉及。即使在 2D 级别,您也可以从这些方法中获得更多信息,例如行向量和列向量、上/下矩阵、矩阵算术等。如果您有任何问题,请告诉我。