【问题标题】:Ignore Ada Function Return Values忽略 Ada 函数返回值
【发布时间】:2012-02-09 07:10:13
【问题描述】:

有没有办法忽略Ada 函数中的返回值?

我有一个从 Intrinsic 导入的函数。

subtype int32 is Interfaces.Interger_32;

function Intrinsic_Sync_Add_And_Fetch
    (P : access int32; I : int32) return int32;

pragma Import(
            Intrinsic, 
            Intrinsic_Sync_Add_And_Fetch, 
            "__sync_add_and_fetch_4");

如果我想在一个过程中使用它,我需要接受返回值,否则我会得到一个编译器错误:

cannot use function Intrinsic_Sync_Add_And_Fetch in procedure call.

但是,如果我创建一个变量,它只接受函数的返回值并且从未使用过,那么我会收到编译器警告。显然,我宁愿避免这些。

我不能很好地将值 back 分配给我要添加的值;这会破坏add 操作的原子性。

可以选择获取价值并用它做一些事情,例如:

val := Intrinsic_Sync_Add_And_Fetch(...);
if val := 0 then null; end if;

它强制代码编译没有错误或警告,但对我来说似乎很愚蠢。我怎样才能“绕过”这个语言特性并安全地忽略返回值?

编辑:什么是 __sync_add_and_fetch_4?

这是 Intel CPU 上可用的内置原子操作。因此,我的Autoconf/Automake 流程的一部分将决定该操作是否可用,如果不可用,则使用涉及关键部分的回退实现。

您可以在GCC's section on atomic builtins 中阅读有关此操作和类似操作的信息。

__sync_add_and_fetch_4 与它所说的几乎完全一样。在C 中,它看起来像这样:

int32_t __sync_add_and_fetch_4(int32_t *ptr, int32_t value) {
    *ptr += value;
    return *ptr;
}

所以它是一个原子加法运算,它返回加法的结果。基本上,它是一个原子+= 运算符。 _4 表示它需要一个 4 字节的整数。

编辑:我知道我可能只是关闭那个特定的编译器警告,但这对我来说总是很脏。如果有可以让我继续使用-Wall -Werror 的解决方案,那么我很乐意看到它。

【问题讨论】:

  • 由于我不知道“__sync_add_and_fetch_4”操作,您能告诉我/我们关于它的用法吗? P 是您要使用的值,而返回值是您要忽略的值吗?
  • 好的,用原子添加操作的小解释更新了问题。是的,我想忽略该函数的返回值。它返回的是操作的结果,它也存储在P 中。我猜它返回相同值的唯一原因是使其可链接。我不需要那个。
  • 感谢您的更新,我建议您使用包装器功能。这是因为在 Ada 中,函数的签名包括返回类型,所以要让编译指示导入正常工作(绑定到正确的东西),你需要一个返回值。您的包装函数规范应该看起来像 Simon Wright 建议的那样,并且具有 oenone 建议的内部。

标签: language-features ada


【解决方案1】:
declare
   dummy : constant return_type := my_function;
   pragma Unreferenced (dummy);
begin null; end;

或者写一个包装过程。

【讨论】:

  • pragma Unreferenced 是 GNAT 特殊的,这可能是一个劣势。
  • 目前似乎是最好的选择。目前我只支持 GNAT,但这可能会改变。
  • @Simon:警告也是 GNAT 特殊的。任何其他编译器可能会有不同的行为。所以 Unreferenced 是有道理的。
【解决方案2】:

如果你不想引用返回值,为什么不将子程序声明为过程呢?该值将在寄存器中返回,因此将其丢弃不会引起太多麻烦。 (我会在这一点上得到纠正!)

subtype int32 is Interfaces.Integer_32;

procedure Intrinsic_Sync_Add_And_Fetch
    (P : access int32; I : int32);

pragma Import(
            Intrinsic, 
            Intrinsic_Sync_Add_And_Fetch, 
            "__sync_add_and_fetch_4");

【讨论】:

  • 好的,很酷。任何人都可以确认这是安全的吗?我想知道如果我导入了一个“错误”的函数签名会发生什么。
【解决方案3】:

您说您只针对 GNAT 编译器。 GNAT User's Guide 说:

请注意,特殊豁免适用于在任何大小写中包含任何子字符串 DISCARD、DUMMY、IGNORE、JUNK、UNUSED 的变量。此类变量被认为可能会被有意使用在否则会发出警告的情况下,因此此类变量始终会禁止此类警告。

因此,解决您的问题的最简单方法是:

unused := Intrinsic_Sync_Add_And_Fetch(...);

如果您要多次使用它,您可能希望将其包装在一个过程中:

procedure Intrinsic_Sync_Add_And_Fetch(P : access int32; I : int32) is
   unused : int32;
begin
   unused := Intrinsic_Sync_Add_And_Fetch(P : access int32; I : int32);
end Intrinsic_Sync_Add_And_Fetch;

【讨论】:

  • 哇,我只是在学习 Ada,但这对于 GNAT 来说似乎是一个非常奇怪的设计决定,魔术变量名称?如果我想使用变量idontcare 怎么办? :P
【解决方案4】:

我不知道有什么方法可以忽略 Ada 中函数的返回值:该语言专门设计用于强制您存储这些返回值。

就我个人而言,我会存储返回值并忽略有关变量使用的任何警告。无论如何,上述警告很奇怪,因为该变量确实用于存储返回值。

【讨论】:

  • 是的,但没有引用该值。这可能是来自 C 和 C++ 的交叉警告。基本上,它是冗余内存,因为它没有被使用。也许如果我用 -On 编译,它会优化它?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-15
  • 2021-11-14
  • 2021-10-03
  • 1970-01-01
相关资源
最近更新 更多