Давайте посмотрим на лес сначала, прежде чем смотреть на деревья.
Здесь есть много информативных ответов с большими подробностями, я не буду повторять ни одного из них. Ключ к программированию в JavaScript имеет сначала правильную ментальную модель общего исполнения.
Хорошие новости заключается в том, что, если вы хорошо понимаете этот момент, вам никогда не придется беспокоиться о гоночных условиях. Прежде всего вы должны понимать, как вы хотите упорядочить свой код как по существу ответ на разные дискретные события, и как вы хотите объединить их в логическую последовательность. Вы можете использовать обещания или новые асинхронные / ожидающие более высокие уровни в качестве инструментов для этой цели, или вы можете откатывать свои собственные.
Но вы не должны использовать какие-либо тактические инструменты для решения проблемы, пока вам не понравится актуальная проблемная область. Нарисуйте карту этих зависимостей, чтобы знать, что нужно запускать, когда. Попытка ad-hoc подхода ко всем этим обратным вызовам просто не поможет вам.
я предложил бы такую альтернативу:
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]
.
Вы используете то, что называется массивом переменной длины , однако есть проблема. В C каждая структура должна иметь определенную длину байта, так что, например, sizeof(struct image)
можно оценить. В вашем случае размер массива переменной длины не может быть определен во время компиляции, поэтому он является незаконным.
В другом случае вам, вероятно, нужны указатели вместо массивов объявленной длины:
typedef struct image
{
int width;
int heigth;
struct pixel **pixels;
};
Отказ от ответственности: ВЛАСы в структурах иногда допускаются, хотя это вопрос, если это расширение является скорее ошибкой, чем функцией. См.: Недокументированное расширение GCC: VLA в struct
Изменить: remyabel указывает на документы GCC, которые говорят о редких ситуациях, в которых VLAs в структурах в порядке: https: //gcc.gnu.org/onlinedocs/gcc/Variable-Length.html#Variable-Length
В C99 и более поздних версиях вы можете иметь (одномерный) элемент гибкого массива (FAM) в конце структуры:
§6.7. 2.1 Спецификаторы структуры и объединения
¶18 В качестве особого случая последний элемент структуры с более чем одним именованным элементом может иметь неполный тип массива; это называется гибким элементом массива . В большинстве ситуаций гибкий элемент массива игнорируется. В частности, размер структуры выглядит так, как если бы гибкий элемент массива был исключен, за исключением того, что он мог иметь более длинное дополнение, чем подразумевалось бы упущение. Однако, когда оператор
blockquote>.
(или->
) имеет левый операнд, который является (указателем на) структуру с гибким членом массива, а правый операнд - этим членом, он ведет себя так, как если бы этот элемент был заменен на самый длинный массив (с тем же типом элемента), который не сделает структуру больше, чем объект, к которому обращаются; смещение массива должно оставаться равным элементу гибкого элемента массива, даже если это будет отличаться от размера массива замены. Если этот массив не будет содержать никаких элементов, он будет вести себя так, как если бы у него был один элемент, но поведение не определено, если предпринимаются какие-либо попытки доступа к этому элементу или для создания указателя за ним.Это означает, что вы могли бы написать:
typedef struct image { int width; int height; struct pixel pixels[]; } image;
, но вам нужно было бы сделать отображение индекса 2D-1D самостоятельно. Вы также должны быть осторожны, как вы выделяете структуру (по необходимости, она будет выделена
malloc()
, так как в противном случае размер массива будет равен нулю).Обратите внимание на исправление орфографии для
height
; обратите внимание также на добавление имени дляtypedef
(я выбралimage
для соответствия тегу структуры, но вы можете выбрать любое другое имя, которое вам нравится). Atypedef
без имени является «действительным», но не полезным - вы можете опустить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); }
m не уверен, что есть хороший способ получить 2D-массив как FAM.