【问题标题】:multidimensional array in struct c结构 c 中的多维数组
【发布时间】:2014-04-29 14:02:50
【问题描述】:

我已经尝试了很长时间。一切似乎都正常,但我收到很多警告,只想正确编程。 问题如下:我正在制作一个游戏引擎。 我提供 3d 数组中的图像,其中前两个索引是位置,第三个是颜色。所以一个简单的 4x4 图像将是:

static const uint8_t font_image[2][2][3] = 
{
    {{255,255,255},{255,255,255}},
    {{255,255,255},{255,255,255}}
};

现在每个实体结构都有一个精灵结构。我想要的只是引用结构中的 3 维数组。

struct Sprite {
    uint32_t sizeX;
    uint32_t sizeY;
    uint8_t * data;
};

每张图片都有自己的宽度和高度,所以我做不到

uint8_t [2][2][3] data;

我不断收到此警告:

消息 3 应为“const uint8_t *”,但参数类型为“const uint8_t (*)[10][4][3]” C:\Users\Elmar\Documents\GitHub\EVA-OS\EVA-OS \Libs\Game\sprite.h 28 10 EVA-OS

这是创建新精灵的函数:

Sprite * sprite_new(uint32_t width, uint32_t height, const uint8_t * image)
{
    Sprite * sprite = malloc(sizeof(Sprite));
    sprite->data = image;
    sprite->sizeX = width;
    sprite->sizeY = height;
    return sprite;
}

提前致谢! :)

【问题讨论】:

  • C 的多维数组处理很糟糕。我认为每个人都倾向于将所有内容展平并手动执行索引逻辑,即使在引入 VLA 之后也是如此。
  • 听起来你很想为每张图片设置static const uint8_t font_image[SIZE_X * SIZE_Y * N],然后data可以指向它。
  • 我想说你已经完美地指出了这个问题:The problem is the following: I'm making a game engine. - 如果你正在制作游戏引擎,迟早你会发现这是你的主要问题:D
  • 哪行代码产生了错误?上面没有 uint8_t*[10][4][3]...
  • 如果你想要的只是对 that 3D 数组的引用,那么 uint8_t (*data)[2][3] 会做你想做的事。函数的参数也是如此。 (而且我很难准确理解“我想要的只是引用结构中的 3 维数组。”在这种情况下真正意味着什么。)

标签: c arrays pointers multidimensional-array struct


【解决方案1】:

从您的错误消息来看,您似乎在代码中的其他地方执行此操作:

uint8_t image[10][4][3] = { ... whatever ... };

Sprite *sprite = sprite_new(10, 4, image);

问题在于编译器认为image 的数据类型是const uint8_t (*)[10][4][3],而不是uint8_t *。你可以让它与演员一起工作:

Sprite *sprite = sprite_new(10, 4, (uint8_t *)image);

至于你如何声明你的Sprite 结构,user2357112 是正确的。确实没有简单的方法来声明可变长度数组并将它们传递给 C 中的函数并保留它们的大小信息。 C在这方面有点愚蠢。您始终需要将尺寸信息作为一个或多个单独的参数传递。

【讨论】:

  • 转换为不兼容的类型在 c 中未定义;你也打破了严格的混叠。您已经编写了一个可能正确的解决方案(传递数组大小),为什么不使用它?
  • 首先,这不是未定义的行为。通过type_xyz * 访问type_xyz 的多维数组不会导致未定义的行为,前提是您使用正确的数组维度进行指针运算。其次,他已经传递了尺寸信息,所以我不确定你在建议我做些什么不同。最后,存在严格的别名规则,因此人们不会执行诸如将struct Foo * 转换为struct Bar * 或将uint32_t * 转换为uint16_t * 之类的事情,因为这些事情可能 导致未定义行为。这没有。
  • C 规范说兼容类型是,我引用:*如果它们的类型相同,则两种类型具有兼容类型。*(201x:6.2.7.1)对此还有其他规则,但没有其中包括将多维指针转换为单个指针。所以这已经是非法的了。
  • 然后我们有别名。根据 201x:6.5.7,一个对象的存储值只能由具有以下类型之一的左值表达式访问,两个重要的行:与有效的类型兼容的类型对象的类型和*一个字符类型。*。你的演员阵容正在破坏。
  • 底层类型 (uint8_t) 在这里很重要。多维数组作为简单的平面缓冲区以完全可预测的顺序排列在内存中。停止引用规则并解释 this example 将如何破坏。至于严格别名,并非所有破坏严格别名的东西都会导致未定义的行为。只需稍微动动脑筋,思考字节级别的实际情况。
【解决方案2】:

之前

sprite->data = image;

您是否为数据分配空间?

我假设您必须为struct Sprite 分配空间,但这只会包含指针空间。然后,您将需要为 regoin 分配空间并让数据指向它。最后,你可以在那个空间里memcopy 东西......

Sprite * sprite = malloc(sizeof(Sprite));
sprite -> data  = malloc( width*length*sizeof(uint8_t)   );
memcopy( ...

【讨论】:

  • 不,在这种情况下 malloc 是不可能的。我的内存空间很小,我正在从闪存存储和加载图像。不过,Malloc 会让一切变得更容易
猜你喜欢
  • 2010-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 2021-09-22
  • 1970-01-01
  • 2020-09-19
  • 2021-12-14
相关资源
最近更新 更多