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

时间:2010-06-22 01:55:22

标签: c

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

char        mValue[MAXROWS][MAXCOLUMNS]; 

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

谢谢!

6 个答案:

答案 0 :(得分:2)

正如之前的海报所说,一个好方法是创建一个线性数组,然后“将其转换为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;

答案 1 :(得分:2)

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

ABCDE
FGHIJ   --->  ABCDEFGHIJKLMNO
KLMNO

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

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

答案 2 :(得分:1)

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

char *p = malloc(ROWS * COLUMNS);

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

答案 3 :(得分:1)

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

#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;
}

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

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

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

//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顺序调用信息将会产生严重问题。