c - 将指针传递给指向 C 结构的指针数组

标签 c pointers struct

我有一个结构:

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);
}

我有一张 map :

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]);
}

编译器不喜欢这样并给我不兼容的指针类型警告。 map 未绘制:

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));
        }
    }
}

最佳答案

问题似乎正是编译器所识别的:您将 __flash 指针传递给需要 __memx 指针的函数。

如果把draw_map的签名改成

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

然后它工作正常。

好吧,当编译器可以接受第一个参数的 __flash 指针(也定义为 __memx)时,为什么这是必要的?

原因是第一个指针按值传递,而第二个指针按引用传递(tileset 是指向 __memx 指针的指针)。

根据 AVR 文档,__flash 指针是指向(显然)闪存的 16 位指针,而 __memx 指针是可以指向位置的 24 位指针在闪存或静态 RAM 中。

看起来编译器足够聪明,在按值传递时将 16 位 __flash 指针提升为 24 位 __memx 指针(类似于它的方式可以将 16 位 short 提升为 32 位 int 或 long),但它不会导致存储在内存中(在您的 IMAGES 数组中)的 16 位指针扩展为 24 位.

由于 __memx 指针比 __flash 指针使用起来更慢(显然编译器必须检查实际指针是指闪存还是静态 RAM,并为每个指针使用不同的指令),如果您知道您的图像和 map 数据将始终在闪存中,只需传递 __flash 指针即可。

关于c - 将指针传递给指向 C 结构的指针数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54505474/

相关文章:

c - 链表中的字符串问题。字段被最后一个节点的输入覆盖

c++ - 内存运行时错误 : where do we delete this pointer

c++ - 是否为堆栈局部数组创建了指针变量?

c# - 在 C# 中使用结构是否有任何内存或 CPU 开销

c - GSL 求解钟摆运动的 ODE

c - 结构值中的类型不匹配

sorting - 如何按字母顺序对结构字段进行排序

go - 有没有办法将结构与 slice 字段与零值结构进行比较?

c++ - 为什么 NULL/0 是对象的非法内存位置?

c - 释放通过 malloc 获得的结构数组