Объясните "массив указателей на линии сканирования" в этом объекте изображения? - PullRequest
1 голос
/ 12 января 2012

Я новичок в C, и эта структура, представляющая изображение, сбивает меня с толку. Это используется в этом Графике Gem .

Может ли кто-нибудь объяснить правильное создание и использование структуры, особенно в отношении массива указателей на линии сканирования?

typedef unsigned char Pixel;

typedef struct {
    short Hres;  /* no. pixels in x direction */
    short Vres;  /* no. pixels in y direction */
    int   Size;  /* size in bytes */
    Pixel *i;    /* pixel array */
    Pixel *p[1]; /* scanline pointer array; position (x,y) given by image->p[y][x] */
}   Image;

Кроме того: является ли смысл избегать неявного умножения при индексации двумерного массива? Разве это не должно быть **p, которое может быть выделено для Vres * sizeof(size_t) и заполнено соответствующими указателями строк?

Обновление
Я думаю, что понял. Этот пример блока действителен?

int m, n, y, x; /* Vres, Hres, index variables */
Image *image;    
image = malloc(sizeof(Image) + (m - 1) * sizeof(Pixel*));
image->Hres = n;
image->Vres = m;
image->Size = m*n*sizeof(Pixel);
image->i = malloc(image->Size);

for (y=0; y<m; y++)
{
    image->p[y] = image->i + (y * n);
    for (x=0; x<n; x++)
    {
        image->p[y][x] = 0; /* or imageSource[y][x] */
    }
}
/* use image */
free(image->i);
free(image);

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

Ответы [ 2 ]

4 голосов
/ 12 января 2012

Pixel *p[1] наиболее вероятно то, что называют «гибким» массивом.

Хитрость заключается в том, чтобы поместить такие массивы в конец struct, а затем выделить блок размером с размерструктура плюс общий размер дополнительных записей массива в конце.Это избавляет вас от необходимости знать точный размер массива при определении структуры, вы скорее указываете его во время выполнения:

Image *img = malloc(sizeof(Image) + 5 * sizeof(Pixel *));
/* img->p[5] is the last element of the array now */

Строго говоря, вы будете обращаться к массиву за его пределами, но вы делаетеэта операция безопасна, зная, что вы зарезервировали достаточно дополнительной памяти после окончания структуры.

4 голосов
/ 12 января 2012

Последний элемент p структуры Image используется в качестве гибкого массива C89 .

Элемент гибкого массива является C99и до C99 люди иногда использовали так называемый struct hack , чтобы добиться аналогичного поведения с C89.

Вот как динамически выделить объект структуры Image только с одним массивомэлемент:

Image *bla1, *bla2;
bla1 = malloc(sizeof *bla1);

и вот как можно выделить объект структуры с n элементами массива:

bla2 = malloc(sizeof *bla2 + (n - 1) * sizeof bla2->p[0]);

После правильной инициализации указателей Pixel * в pмассив, вы можете получить доступ к Pixel значениям, как это:

bla2->p[x][y]

Относительно соответствия struct hack , C99 Обоснование говорит, что

достоверность этой конструкции всегда была сомнительной.

, в то время как в отчете о дефектах C (DR # 051) говорится, что

Эта идиома, хотя и распространена, не является строго соответствующей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...