C инициализировать массив внутри структуры
Я хочу иметь массив переменной длины, содержащийся внутри структуры, но у меня проблемы с его инициализацией правильно.
struct Grid {
int rows;
int cols;
int grid[];
}
int main() {
struct Grid testgrid = {1, 3, {4, 5, 6}};
}
Все, что я пытаюсь, дает мне ошибку: нестатическая инициализация ошибки гибкого члена массива.
Ответы
Ответ 1
Вы можете сделать эту работу в gcc, сделав struct либо static
, либо глобальным, но оказывается, что инициализация элементов гибкого массива несоответствует и поэтому, скорее всего, не будет работать, кроме как с gcc. Вот способ сделать это, что просто использует C99-совместимые функции...
#include <stdlib.h>
#include <stdarg.h>
typedef struct Grid {
int rows;
int cols;
int grid[];
} *Grid;
Grid newGrid(int, int, ...);
Grid newGrid(int rows, int cols, ...)
{
Grid g;
va_list ap;
int i, n = rows * cols;
if((g = malloc(sizeof(struct Grid) + rows * cols * sizeof(int))) == NULL)
return NULL;
g->rows = rows;
g->cols = cols;
va_start(ap, cols);
for(i = 0; i < n; ++i)
g->grid[i] = va_arg(ap, int);
va_end(ap);
return g;
}
.
.
.
Grid g1, g2, g3;
g1 = newGrid(1, 1, 123);
g2 = newGrid(2, 3, 1, 1, 1,
2, 2, 2);
g3 = newGrid(4, 5, 1, 2, 3, 4, 5,
6, 7, 8, 9, 10,
11, 12, 13, 14, 15,
16, 17, 18, 19, 20);
Ответ 2
Вот моя версия:
#include <stdio.h>
struct matrix {
int rows;
int cols;
int **val;
} a = { .rows=3, .cols=1,
.val = (int*[3]){ (int[1]){1},
(int[1]){2},
(int[1]){3} } },
b = { .rows=3, .cols=4,
.val = (int*[3]){ (int[4]){1, 2, 3, 4},
(int[4]){5, 6, 7, 8},
(int[4]){9,10,11,12} } };
void print_matrix( char *name, struct matrix *m ){
for( int row=0;row<m->rows;row++ )
for( int col=0;col<m->cols;col++ )
printf( "%s[%i][%i]: %i\n", name, row, col, m->val[row][col] );
puts("");
}
int main(){
print_matrix( "a", &a );
print_matrix( "b", &b );
}
Ответ 3
У вас нет массива переменной длины (VLA) в вашей структуре. То, что у вас есть в вашей структуре, называется гибким элементом массива. Элемент гибкого массива не имеет абсолютно никакого отношения к VLA. Гибкие элементы массива в C существуют, чтобы легализовать и поддерживать добрую ирригацию "struct hack", которая основана на динамическом распределении памяти для объектов struct с трейлинг-массивами разного размера.
Элементы гибкого массива не могут быть инициализированы с помощью агрегатных инициализаторов, которые, как вам кажется, пытаются выполнить в вашем коде. То, что вы пытаетесь сделать здесь, просто невозможно. В C нет такой функции.
Между тем текст сообщения об ошибке, сгенерированного вашим компилятором, кажется, предполагает, что он поддерживает что-то вроде этого в качестве расширения. Это может быть правдой, но имейте в виду, что это никоим образом не является стандартной функцией C.
Ответ 4
Я не считаю, что это возможно или поддерживается. Как отмечает DigitalRoss, вы можете инициализировать из литерала в случае массивов static
... хотя я все еще не уверен, что это включено в стандарт или просто общее расширение. Кажется, я не могу найти предложение в стандарте, которое поддерживает литеральную инициализацию гибких массивов, хотя я вижу, что gcc явно поддерживает его.
Ответ 5
Версия с использованием malloc:
#include <stdio.h>
#include <stdlib.h>
typedef struct Grid {
int rows;
int cols;
int *grid;
} Grid;
/* Should validate params */
Grid
buildGrid(int rows, int cols, int vec[]) {
Grid grid;
grid.rows = rows;
grid.cols = cols;
int i;
if ( (grid.grid = malloc(sizeof(vec))) == NULL ) {
/* do something.*/
}
for(i = 0; i < sizeof(vec) ; i++ ) {
grid.grid[i] = vec[i];
}
return grid;
}