如您所学,C语言中没有二维数组。只有模拟二维数组索引的方法。这些方法分为两类:(1)创建指向数组的指针数组,(2)创建普通的顺序数组,并使用索引算术在二维方式下引用元素。在每种情况下,可以根据数组中元素总数(或数组大小)和要模拟的列数(或数组步幅)来考虑算术运算。通过仔细的索引,知道数组的大小和步幅,您可以将C语言的一维数组用作二维数组。为了帮助解决关于两种类型、指针和索引的任何问题,考虑以下内容:
指针类型数组
首先,当您使用“指向类型的指针数组”(例如,int **array)时,您需要分配ROWS个指向类型为COLS的数组的指针(本质上,您有ROWS个大小为COLS的数组)。然后,通过解除引用,您可以将元素索引为二维数组(例如,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()
您可以使用简单的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;
将线性数组视为二维数组
在这种情况下,您使用传统的顺序1D数组来保存数据,声明和分配数组很简单:
int *array = NULL;
...
array = xcalloc (size, sizeof *array);
注意:要以类似于访问指向数组的指针的情况相同的逻辑存储数组中的值,以便以模拟二维方式访问数组元素。从循环的角度来看,您将使用与指向数组的指针相同的逻辑来访问数组的值。唯一的区别在于索引的计算:
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;
if (size < stride || size % stride) {
fprintf (stderr, "error: invalid stride '%d' for %d element array.\n",
stride, size);
return 1;
}
srand (time(NULL));
array = xcalloc (size/stride, sizeof *array);
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;
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');
}
if (stride > 1)
printf ("\n array[1][1] in (%d x %d) array : %d\n\n",
size/stride, stride, array[1][1]);
for (i = 0; i < size/stride; i++)
free (array[i]);
free (array);
return 0;
}
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
示例 - 将线性数组视为2D数组
#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;
if (size < stride || size % stride) {
fprintf (stderr, "error: invalid stride '%d' for %d element array.\n",
stride, size);
return 1;
}
srand (time(NULL));
array = xcalloc (size, sizeof *array);
for (i = 0; i < size/stride; i++)
for (j = 0; j < stride; j++)
array[i * stride + j] = rand() % 1000;
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');
}
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;
}
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级别上,您也可以从这些方法中获得更多的收益,如行向量、列向量、上/下三角矩阵、矩阵算术等。如果您有任何问题,请让我知道。
int (*a)[in_size] = malloc(sizeof(int[in_size][in_size]));
来分配一个二维数组,然后你就可以一次性地得到一个连续的数组。对于这样的数组,即使是你粗糙的初始化技巧(实际上没有什么作用)也能起作用。 - Jens Gustedt