Ada:记录类型的变体大小 [英] Ada : Variant size in record type

查看:156
本文介绍了Ada:记录类型的变体大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Ada记录类型时出现问题。
我正在使用Sequential_IO来读取二进制文件。要做到这一点,我必须使用大小是文件大小的倍数的类型。在我的情况下,我需要一个50字节的结构,所以我创建了一个这样的类型(Vecteur是一个3 Float的数组):

I having some trouble with the type Record with Ada. I'm using Sequential_IO to read a binary file. To do that I have to use a type where the size is a multiple of the file's size. In my case I need a structure of 50 bytes so I created a type like this ("Vecteur" is an array of 3 Float) :

type Double_Byte is mod 2 ** 16; for Double_Byte'Size use 16;

type Triangle is
    record
        Normal : Vecteur(1..3);
        P1 : Vecteur(1..3);
        P2 : Vecteur(1..3);
        P3 : Vecteur(1..3);
        Byte_count1 : Double_Byte;
    end record;

当我使用类型三角形时,大小为52字节,但当我取每个的大小时在其中我发现50个字节。因为52不是我文件大小的倍数,所以我有执行错误。但我不知道如何修复这个大小,我运行了一些测试,我认为它来自Double_Byte,因为当我从记录中删除它时,我发现它的大小为48字节,当我把它放回去时它再次是52字节。

When I use the type triangle the size is 52 bytes, but when I take the size of each one separetely within it I find 50 bytes. Because 52 is not a multiple of my file's size I have execution errors. But I don't know how to fix this size, I ran some test and I think it come from Double_Byte, because when I removed it from the record I found a size of 48 bytes and when I put it back it's 52 bytes again.

感谢您的帮助。

推荐答案

编译器在除非您指定,否则没有义务为 Triangle 使用特定大小。如果不这样做,它会选择它认为适合的任何大小来快速访问数据。即使您为记录的每个组件类型指定了表示详细信息,编译器仍可能选择为记录本身使用更多空间而不是必要。

The compiler is in no way obligated to use a specific size for Triangle unless you specify it. As you don't, it chooses whatever size it sees fit for fast access to the data. Even if you specify representation details for every component type of the record, the compiler might still choose to use more space for the record itself than necessary.

考虑到您提供的大小,很明显, Vecteur 的一个组件有4个字节,这为 Triangle 提供了50个字节的总有效负载。编译器现在选择添加2个字节的填充,以便记录大小是 4字节字。您可以使用以下方式覆盖此行为:

Considering the sizes you give, it seems obvious that one component of Vecteur has 4 bytes, which gives a total payload of 50 bytes for Triangle. The compiler now chooses to add 2 bytes padding, so that the record size is a multiple of the size of a 4-byte word. You can override this behavior with:

for Triangle'Size use 50 * 8;

这将强制编译器仅使用50个字节作为记录。由于这是一个紧密配合,只有一种方法来表示记录,不需要进一步的说明。如果确实需要指定记录的准确程度,可以使用记录表示条款

This will force the compiler to use only 50 bytes for the record. As this is a tight fit, there is only one way to represent the record, and no further specification is necessary. If you do need to specify how exactly the record is represented, you can use a record representation clause.

编辑:

表示子句指定类型的大小。但是,除非另外指定

The representation clause specifies the size for the type. However, each object of this type may still take up more space unless you additionally specify

pragma Pack (Triangle);

编辑2:

在Simon的评论之后,我仔细研究了这一点,并意识到有一个更好,更清洁的解决方案。而不是设置'大小并使用 pragma Pack ,请执行以下操作:

After Simon's comment, I had a closer look at this and realized that there is a far better and cleaner solution. Instead of setting the 'Size and using pragma Pack, do this:

for Triangle use record at mod 2;
   Normal      at 0  range 0 .. 95; 
   P1          at 12 range 0 .. 95;
   P2          at 24 range 0 .. 95;
   P3          at 36 range 0 .. 95;
   Byte_count1 at 48 range 0 .. 15;
end record;

初始 mod 2 定义记录将以2个字节的倍数对齐。这消除了最后的填充,而不需要 pragma Pack (不保证在每个编译器上以相同的方式工作)。

The initial mod 2 defines that the record is to be aligned at a multiple of 2 bytes. This eliminates the padding at the end without the need of pragma Pack (which is not guaranteed to work the same way on every compiler).

这篇关于Ada:记录类型的变体大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆