使用数组初始化器作为静态数组

时间:2014-01-07 14:31:03

标签: c arrays segmentation-fault

是否可以将数组初始值设定项用作数组(有点像字符串文字?)

#define TETRAMINO_I {{1,1,1,1},{0,0,0,0}}

printf("%c",(TETRAMINO_I[0][0]) ? "#" : ' ');

(这段代码显然不起作用。

我提出了以下解决方案(绕过此要求)

#define TETRAMINO_I {{1,1,1,1},{0,0,0,0}}
#define TETRAMINO_J {{1,1,1,0},{0,0,1,0}}
#define TETRAMINO_L {{1,1,1,0},{1,0,0,0}}
#define TETRAMINO_O {{1,1,0,0},{1,1,0,0}}
#define TETRAMINO_S {{0,1,1,0},{1,1,0,0}}
#define TETRAMINO_T {{1,1,1,0},{0,1,0,0}}
#define TETRAMINO_Z {{1,1,0,0},{0,1,1,0}}

typedef unsigned char byte;

typedef struct tetraminos{
    char I[2][4];
    char J[2][4];
    char L[2][4];
    char O[2][4];
    char S[2][4];
    char T[2][4];
    char Z[2][4];

}tet_minos_t;

tet_minos_t tet_mino_blocks{ TETRAMINO_I,TETRAMINO_J,TETRAMINO_L,TETRAMINO_O,TETRAMINO_S,TETRAMINO_T,TETRAMINO_Z};

使用结构的全局实例。但是,在尝试使用时:

newMino->blocks = (char**)tet_mino_blocks.I;
printf("%c",(newMino->blocks[0][0]) ? "#" : ' ');

我无法打印(获取分段错误)

2 个答案:

答案 0 :(得分:2)

是的,有点,但你必须给你的阵列一个类型。自C99以来,我们有复合文字:

#define TETRAMINO_C ((unsigned char const[][4])TETRAMINO_I)

这为数组提供了const - 限定类型(在语法上类似于强制转换)。类型为const - 限定,因此编译器对如何分配数组的约束较少(如果必须)。允许为数组的所有使用分配一个静态副本。

但是如果你只使用TETRAMINO_C[0][0]中指出的那么现代C编译器的一个不错的优化器应该能够完全优化数组并且只能直接使用常量。

答案 1 :(得分:1)

问题是char[2][4]没有描述与char **相同的内存布局。第一个是char的连续二维数组,而第二个是指向char的指针数组的指针。您最终将字符值视为指针,这当然会导致无效的地址和段错误。

为了使代码正常工作,newMino->blocks指针必须是char *[4]类型,而不是类型char **。像这样定义:

struct ... {
    char (*blocks)[4];
};

typedef char[4] tetromino_col_t;
struct ... {
    tetromino_col_t *blocks;
};