Передать указатель на массив указателей на структуру C - PullRequest
0 голосов
/ 03 февраля 2019

У меня есть структура:

typedef struct Image {
    byte height;
    byte width;
    byte data[];
} Image;

, и я создаю 2 изображения:

static const __flash Image GRID = {
    .width = 16,
    .height = 8,
    .data = {
        0x10, 0x10, 0x28, 0x28, 0x44, 0x44, 0x82, 0x82, ...
    }    
};

static const __flash Image HOUSE1 = {
    .width = 24,
    .height = 24,
    .data = {
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ...
    }
};

Затем я создаю массив указателей на изображения:

static const __flash Image *IMAGES[] = {
    &GRID,
    &HOUSE1,
};

Я могу нарисовать изображение, используя мою draw_image() функцию:

void main(void)
{
    draw_image(IMAGES[0], 16, 16);
}

У меня есть карта:

typedef struct Map {
    word cols;
    word rows;
    byte tiles[];
} Map;

static const __flash Map level_1 = {
    .cols = 16,
    .rows = 8,
    .tiles = {
        0,0,1,0,...

поле .tiles представляет собой список индексов в IMAGES массив.Я делаю это таким образом, потому что мой движок не знает, какие изображения доступны, без уведомления:

void draw_map(const Map __memx *map, const Image __memx *tileset[]);
{
    ...
    draw_image(tileset[map->tiles[index]], x, y);
    ...
}

, названный так:

void main(void)
{
    draw_map(&level_1, &IMAGES[0]);
}

Компилятору это не нравится ивыдает мне несовместимые предупреждения типа указателя.Карта не прорисована:

note: expected 
‘const __memx Image ** {aka const __memx struct Image **}’
but argument is of type 
‘const __flash Image ** {aka const __flash struct Image **}’

Я попытался удалить [] из объявления draw_map():

void draw_map(const Map __memx *map, const __memx Image *tileset);

, но это вызвало ошибку при вызове draw_image() Звоните:

error: incompatible type for argument 1 of ‘draw_image’
             draw_image(tileset[0], c*8+(64 - r*8), r*8);
                        ^
tile-engine.c:63:6: note: expected 
‘const __memx Image * {aka const __memx struct Image *}’ but argument is of type 
‘Image {aka const __memx struct Image}’

Где я иду не так?

void draw_image(const Image __memx *image, int x, int y)
{
    byte rows = image->height>>3;
    byte cols = image->width>>3;

    for(byte r=0 ; r<rows ; r++)
    {
        for(byte c=0 ; c<cols ; c++)
        {
            draw_tile(&image->data[(r*cols+c)*8], &image->data[(r*cols+c)*8], x+(c*8), y+(r*8));
        }
    }
}

1 Ответ

0 голосов
/ 03 февраля 2019

Похоже, проблема именно в том, что определил компилятор: вы передаете указатель __flash на функцию, которая требует указатель __memx.

Если вы измените сигнатуру draw_map на

void draw_map(const Map __memx *map, const Image __flash *tileset[])

тогда все работает нормально.

Хорошо, почему это необходимо, когда компилятор согласен с принятием указателя __flash для первого аргумента, который также определяется как __memx?

Причина в том, что первый указатель передается по значению, а второй - по ссылке (tileset - указатель на указатель __memx).

В соответствии сВ документации AVR указатели __flash - это 16-разрядные указатели на (очевидно) флэш-память, а указатели __memx - это 24-разрядные указатели, которые могут указывать на местоположения во флэш-памяти или в статической ОЗУ.

Это выглядитнапример, компилятор достаточно умен, чтобы выдавать 16-разрядный указатель __flash на 24-разрядный указатель __memx при передаче его по значению (аналогично тому, как он может преобразовать 16-разрядное короткое в 32-разрядное целое или длинное), но не можетиспользуйте 16-битный указатель, который хранится в памяти (в вашем массиве IMAGES), для расширения до 24 бит.

Поскольку указатели __memx используются медленнее, чем указатели __flash (очевидно, компилятор долженпроверьте, относится ли фактический указатель к флэш-памяти или статическому ОЗУ, и используйте разные инструкции для каждого), если вы знаете, что ваше изображение и данные карты всегда будут во флэш-памяти, просто передайте __flash указатели.

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