繁体   English   中英

声明一个未知大小的二维数组,C

[英]Declaring a 2-dimensional array of unknown size, C

我有一个数组声明为C中的结构的成员。该数组声明为:

char        mValue[MAXROWS][MAXCOLUMNS]; 

其中MAXROWSMAXROWS是300.有更好的方法吗? 我的意思是,我应该将它们声明为指针吗?

谢谢!

正如之前的海报建议的那样,一个好方法是创建一个线性数组,然后“将其转换为2D”。 很多时候,缓存2D指针会大大提高使用此数组的程序的速度,如下所示:

mystruct *p = (mystruct*)calloc(ROWS * COLUMNS, sizeof(mystruct));
mystruct **p2 = (mystruct**)calloc(ROWS, sizeof(mystruct*));
for (int i = 0; i < ROWS; i++)
    p2[i] = p + i*COLUMNS;

然后,您可以使用以下命令访问2D元素:

p2[row][column] = foo;

如果所有行的大小相同,则应使用一维数组,其中行按顺序存储:

ABCDE
FGHIJ   --->  ABCDEFGHIJKLMNO
KLMNO

i行,第j列的元素将位于1D数组中的索引i * ROW_LENGTH + j

您可以使用malloc(ROW_LENGTH * NUM_ROWS)分配数组。

另一种技术是创建一个线性数组,然后将其转换为2d:

char *p = malloc(ROWS * COLUMNS);

// To access x, y
// This is in row-major ordr
*(p + (x * COLUMNS) + y);

我发现,对于这种代码,最好创建辅助函数来访问元素。 根据您的分析数据,将这些转换为宏可能是有意义的,但要格外小心。

#include <stdio.h>  /* For printf */

/* This is the bit that would go in a header, like char2darray.h */
#include <stdlib.h> /* For calloc */
#include <assert.h> /* For assert */

struct Char2DArray
{
   int rows;
   int columns;
   char *values;
};

/* This is the bit that would go in a source file, like char2darray.c */

void C2DA_initialize(struct Char2DArray *array, int rows, int columns)
{
    assert(array != 0);
    array->values = calloc(rows * columns, sizeof(char));
    array->rows = rows;
    array->columns = columns;
}

void C2DA_set(struct Char2DArray *array, int row, int column, int value)
{
    assert(array != 0);
    assert(array->values != 0);
    assert(row < array->rows);
    assert(row >= 0);
    assert(column < array->columns);
    assert(column >= 0);

    array->values[(row * array->rows) + column] = value;
}

char C2DA_get(struct Char2DArray *array, int row, int column)
{
    assert(array != 0);
    assert(array->values != 0);
    assert(row < array->rows);
    assert(row >= 0);
    assert(column < array->columns);
    assert(column >= 0);

    return array->values[(row * array->rows) + column];
}

void C2DA_free(struct Char2DArray *array)
{
    free(array->values);
    array->values = 0;
}

/* Here's a main.c to use it */
int main()
{
    struct Char2DArray a;
    C2DA_initialize(&a, 16, 16);
    unsigned char c = 0;
    int x, y;
    for (x=0; x<16; x++) {
        for (y=0; y<16; y++) {
            C2DA_set(&a, x, y, (char)c);
            c++;
        }
    }
    printf("Character with hex value 0x55 is %c\n", C2DA_get(&a, 5, 5));
    C2DA_free(&a);
    return 0;
}

如果数组需要具有动态大小,那么您需要使其成为指针或使数组成为结构的最后一个成员并在分配结构大小时玩游戏。

相关comp.lang.c常见问题条目:

我发现在面对类似的问题时,改变我的方法非常有用。

向量向量填充相同的任务,避免了内存分配障碍,并保持相同的熟悉的速记。 可能还有其他陷阱,但我还没有遇到过它们。

//Declaration of mValues, undefined size:
std::vector< std::vector<char> > mValues; 

//Filling of mValues:
    int max_x = 100 ;
    int max_y = 100 ;
    char char_foo = 'a';
    for ( int x = 0; x <= max_x; ++x ) {
        vector<char> temp;
        for ( int y = 0; y <= max_y; ++y ) {
             temp.push_back( char_foo );
        }
        mValues.push_back( temp );
    }

// Referencing with familiar index notation:
    mValues[a][b]; //The a-th row's b-th element

如果您正在努力使用数组,但强烈希望使用熟悉的索引语言,我发现这是一个很好的选择。

请注意,在调用此数据时,索引顺序A和B对于内存使用至关重要。 如果性能问题,如果未按A,B顺序调用信息将会出现严重问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM