【问题标题】:Comparing an unknown type against a negative value将未知类型与负值进行比较
【发布时间】:2013-09-14 19:05:31
【问题描述】:

我有一个变量id,其类型可能因平台而异。在几个地方,现有代码(我无法更改)将id 设置为“负”值,例如

id = -ETIMEDOUT;

在某些平台上,id 可能会被签名;在其他人身上,它可能没有签名。我想测试一下id 是否设置为-ETIMEDOUT。当id 未签名时,下面的天真尝试会巧妙地失败:

if(id == -ETIMEDOUT)

我如何简明地测试这种情况?

【问题讨论】:

  • 为什么不只测试if(id == (idtype)-ETIMEDOUT),其中idtypeid 声明为的任何类型(可能是typedef)?

标签: c unsigned-integer platform-agnostic


【解决方案1】:

@jlahd 发布了一个很好的答案。不过我想提供一个替代方案。

if (id == (typeof(id)) -ETIMEDOUT)

我认为这会做类似的事情,但它有一个问题。它不在 C 标准中,是 GCC 扩展。

您可以阅读更多关于它的信息here

逐字引用@rici 的评论:

由于您可能知道一些 typedef 可以作为 id 的类型,因此您大概可以不使用 typeof 来执行此操作,尽管这样更简洁。不过应该是

(typeof(id))(-ETIMEDOUT) 

(-ETIMEDOUT 周围的括号只是装饰性的,但一元减号是必需的。)或者,以下内容应该非常万无一失:

if (-id == ETIMEDOUT)

因为如果 id 是签名的,那显然是有效的;如果 id 是无符号的,则一元减号具有明确定义的行为。

【讨论】:

  • 因为你可能知道一些 typedef 可以作为id 的类型,你大概可以在没有typeof 的情况下执行此操作,尽管这样更简洁。但是,它应该是 (typeof(id))(-ETIMEDOUT)-ETIMEDOUT 周围的括号只是装饰性的,但一元减号是必需的。)或者,以下应该是非常万无一失的:if (-id == ETIMEDOUT),因为如果 id 被签名,那显然作品;如果id 是无符号的,则一元减号具有明确定义的行为。
  • @rici 我很喜欢你的评论,如果你不介意的话,我会在我的回答中一字不差地附上。
  • @rici 如果您决定将此作为您自己的答案,请告诉我,我将删除编辑。在此处发表评论可能是引起我注意的最佳方式。
【解决方案2】:

试试这个:

id += ETIMEDOUT;
if(id == 0) { /* timed out */ }
id -= ETIMEDOUT; /* if you need to keep id untouched */

【讨论】:

  • 大声笑,在任何人有机会说这在“非二进制补码算术机”上不起作用之前,我想请他们在发布回复之前说出今天正在使用的一个...
  • @nonsensical:嗯,实际上,如果你溢出一个有符号的 int,它就是 UB。即使系统是二进制补码,编译器也可以在这种情况下做“意外”的事情。
  • +1 -- 这个解决方案是合理的,但它有点麻烦,特别是如果我必须最终测试六个错误。
  • @nneonneo 正确。但是,我认为由于这是 C,除非您想要一个效率极低的代码,否则您的编译器将永远不会检查溢出,这将留给硬件以定义的方式处理它。但是好的,标准确实说它是 UB。
  • @nonsensical:在某些情况下,编译器可以编译掉依赖于 UB 的检查。 (最突出的例子是无限循环,例如for(int i=5; i != 4; i++);编译器可以优化掉测试,即使它最终应该环绕并终止)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 2010-12-30
  • 1970-01-01
  • 2015-01-31
  • 2019-05-28
  • 2011-07-01
  • 1970-01-01
相关资源
最近更新 更多