接口 Ada 枚举和 C 枚举

por*_*ton 3 enums ada type-conversion

让在 C 代码中定义:

typedef enum { A=1, B=2 } option_type;

void f(option_type option);

让我们也有 Ada 代码:

类型 Option_Type 是 (A, B);
对于 Option_Type'Size 使用 Interfaces.C.int'Size;
对于 Option_Type 使用 (A=>1, B=>2);

X: Option_Type := A;

以下哪个代码是正确的(相应地为 RM)?

-- 第一个代码

宣布
   程序 F(选项:Option_Type)
      使用导入,约定=> C,外部名称=>“f”;
开始
   F(X);
结尾;

或者

-- 第二个代码

宣布
   过程 F(选项:Interfaces.C.unsigned)
      使用导入,约定=> C,外部名称=>“f”;
   函数 Conv 是新的 Ada.Unchecked_Conversion(Option_Type, Interfaces.C.unsigned);
开始
   F(转化率(X));
结尾;

我认为第一个和第二个 Ada 片段都是正确的,但我不确定。

Kei*_*son 5

两者都不是 100% 正确的。

在 C 中:

typedef enum { A=1, B=2 } option_type;
Run Code Online (Sandbox Code Playgroud)

在阿达:

type Option_Type is (A, B);
for Option_Type'Size use Interfaces.C.int'Size;
for Option_Type use (A=>1, B=>2);
Run Code Online (Sandbox Code Playgroud)

Ada 代码假定 C 类型与 Coption_type具有相同的大小int。您的第二个代码段假定它与 C 具有相同的表示形式unsigned int

C 标准不支持这两种假设。

引用N1570草案,第6.7.2.2节,第 4 段:

每个枚举类型应与char、有符号整数类型或无符号整数类型兼容。类型的选择是实现定义的,但应能够表示枚举的所有成员的值。

因此,C 类型option_type可以窄至 1 个字节或与支持的最宽整数类型(通常为 8 个字节)一样宽,并且它可以是有符号的或无符号的。C 将枚举常量的值限制在 type 的范围内int,但这并不意味着类型本身与int-- 或与unsigned int.

如果您了解正在使用的特定 C 编译器的特征(短语“实现定义”意味着必须记录这些特征),那么您可以依赖这些特征——但您的代码将是非-便携的。

我不知道有任何完全可移植的方式来定义与给定 C 枚举类型兼容的 Ada 类型。(我已经离开 Ada 很长时间了,所以我可能会遗漏一些东西。)

我能想到的唯一可移植方法是编写一个 C 包装函数,它接受一个指定整数类型的参数并调用f(). option_type然后由 C 编译器处理从整数类型到整数类型的转换,包装器向 Ada 公开一个带有已知类型参数的函数。

void f_wrapper(int option) {
    f(option); /* the conversion from int to option_type is implicit */
}
Run Code Online (Sandbox Code Playgroud)

  • @porton:不,自 1989 年 ANSI 标准以来,C 标准在这方面没有显着变化。枚举 *constant* 的类型是 `int`。枚举 *type* 与某些实现定义的整数类型兼容。对于具有少量值的枚举类型,编译器可能会合理地将其设为 1 个字节。 (2认同)