Почему я не могу найти указатель массива, определенный в struct? [Дубликат]

Давайте посмотрим на лес сначала, прежде чем смотреть на деревья.

Здесь есть много информативных ответов с большими подробностями, я не буду повторять ни одного из них. Ключ к программированию в JavaScript имеет сначала правильную ментальную модель общего исполнения.

  1. Ваша точка входа (ов) выполняется в результате события. Например, в браузер загружается тег сценария с кодом. (Соответственно, поэтому вам, возможно, придется заботиться о готовности страницы запускать ваш код, если он требует, чтобы элементы dom были сконструированы первыми и т. Д.)
  2. Ваш код выполняется до завершения, однако многие асинхронные вызовы, которые он делает, без выполнения каких-либо ваших обратных вызовов, включая запросы XHR, установку тайм-аутов, обработчиков событий dom и т. д. Каждый из этих обратных вызовов, ожидающих выполнения, будет находиться в очереди, ожидая, что их очередь будет запущена после других событий
  3. Каждый отдельный обратный вызов XHR-запроса, установленного таймаута или dom события после вызова будет завершен.

Хорошие новости заключается в том, что, если вы хорошо понимаете этот момент, вам никогда не придется беспокоиться о гоночных условиях. Прежде всего вы должны понимать, как вы хотите упорядочить свой код как по существу ответ на разные дискретные события, и как вы хотите объединить их в логическую последовательность. Вы можете использовать обещания или новые асинхронные / ожидающие более высокие уровни в качестве инструментов для этой цели, или вы можете откатывать свои собственные.

Но вы не должны использовать какие-либо тактические инструменты для решения проблемы, пока вам не понравится актуальная проблемная область. Нарисуйте карту этих зависимостей, чтобы знать, что нужно запускать, когда. Попытка ad-hoc подхода ко всем этим обратным вызовам просто не поможет вам.

3
задан Haris 3 October 2014 в 18:42
поделиться

3 ответа

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

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].

1
ответ дан HuStmpHrrr 24 August 2018 в 07:59
поделиться

Вы используете то, что называется массивом переменной длины , однако есть проблема. В 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

4
ответ дан Community 24 August 2018 в 07:59
поделиться

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

§6.7. 2.1 Спецификаторы структуры и объединения

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

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

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

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

Обратите внимание на исправление орфографии для height ; обратите внимание также на добавление имени для typedef (я выбрал image для соответствия тегу структуры, но вы можете выбрать любое другое имя, которое вам нравится). A 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);
}

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

4
ответ дан Jonathan Leffler 24 August 2018 в 07:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: