Массив переменной длины в структуре

Я создал 2 структуры для представления изображений (пиксель и изображение один) в C.

typedef struct pixel { unsigned char red; unsigned char green; unsigned char blue; }; typedef struct image { int width; int heigth; struct pixel pixels[width][heigth]; }; 

Я получаю сообщение о том, что ширина и высота не определены в определении изображения. Я не понимаю, почему я получаю эту ошибку и как я могу ее решить

я бы предложил такую ​​альтернативу:

 typedef struct { int width; int heigth; struct pixel *pixels; } image; 

каждый раз вам нужно выделить:

 image img; /* init */ img.pixels=malloc(sizeof(struct pixel)*img.width*img.height); 

*(img.pixels+img.height*i+j) представляет img.pixels[i][j] .

В C99 и более поздних версиях вы можете иметь (одномерный) элемент гибкого массива (FAM) в конце структуры:

§6.7.2.1 Специфика структуры и союза

¶18 В качестве особого случая последний элемент структуры с более чем одним именованным элементом может иметь неполный тип массива; это называется гибким элементом массива . В большинстве ситуаций гибкий элемент массива игнорируется. В частности, размер структуры выглядит так, как если бы гибкий элемент массива был исключен, за исключением того, что он мог иметь более длинное дополнение, чем подразумевалось бы упущение. Однако, когда a . (или -> ) имеет левый операнд, который является (указателем на) структуру с гибким членом массива, а правый операнд – этим членом, он ведет себя так, как если бы этот элемент был заменен самым длинным массивом (с тем же типом элемента ), который не сделает структуру больше, чем объект, к которому обращаются; смещение массива должно оставаться равным элементу гибкого элемента массива, даже если это будет отличаться от размера массива замены. Если этот массив не будет содержать никаких элементов, он будет вести себя так, как если бы у него был один элемент, но поведение не определено, если была предпринята попытка доступа к этому элементу или для создания указателя, который прошел мимо него.

Это означает, что вы могли бы написать:

 typedef struct image { int width; int height; struct pixel pixels[]; } image; 

но вам нужно будет сделать 2D-к-1D-индексирование самостоятельно. Вы также должны быть осторожны, как вы распределяете структуру (по необходимости, она будет выделена malloc() как в противном случае размер массива будет равен нулю).

Обратите внимание на исправление орфографии по height ; обратите внимание также на добавление имени для typedef (я выбрал image для соответствия тегу структуры, но вы можете выбрать любое другое имя, которое вам нравится). typedef без имени является «действительным», но не полезным – вы можете опустить typedef и получить тот же результат.

Вы можете использовать:

 image *ip = malloc(sizeof(image) + width * height * sizeof(struct pixel)); if (ip != 0) { ip->width = width; ip->height = height; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) ip->pixels[i*width + j] = default_pixel_value; } …use ip… free(ip); } 

Я не уверен, что есть хороший способ получить 2D-массив как FAM.

Вы используете так называемый массив переменной длины , однако есть проблема. В C каждая структура должна иметь определенную длину байта, так что, например, sizeof(struct image) может быть оценена. В вашем случае размер массива переменной длины не может быть определен во время компиляции, поэтому он является незаконным.

На другой ноте вам, вероятно, понадобятся указатели, а не массивы объявленной длины:

 typedef struct image { int width; int heigth; struct pixel **pixels; }; 

Отказ от ответственности: ВЛАС в структурах иногда допускается, хотя, по общему мнению, это расширение является скорее ошибкой, чем функцией. См .: Недокументированное расширение GCC: VLA в структуре

Изменить: remyabel указывает на документы GCC, которые рассказывают о редких ситуациях, в которых VLAs в структурах в порядке: https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html#Variable-Length