2

使用 GCC(对我来说是 4.0)是否合法:

if(__builtin_expect(setjmp(buf) != 0, 1))
  {
    // handle error
  }
else
  {
    // do action
  }

我发现一个讨论说它在 2003 年给 GCC 带来了问题,但我想他们现在应该已经解决了。C标准说,setjmp除非它是四个条件之一,否则使用是非法的,相关的一个是:

  • 关系或相等运算符的一个操作数与另一个操作数是整数常量表达式,结果表达式是选择或迭代语句的整个控制表达式;

但如果这是一个 GCC 扩展,我能否保证它适用于 GCC,因为它已经是非标准功能?我对它进行了测试,它似乎可以工作,但我不知道我需要做多少测试才能真正打破它。(我将调用隐藏__builtin_expect在宏后面,该宏被定义为非 GCC 的无操作,因此对于其他编译器来说是完全合法的。)

4

2 回答 2

0

我认为该标准所谈论的内容是为了说明做这样的事情:

int x = printf("howdy");
if (setjmp(buf) != x ) {
    function_that_might_call_longjmp_with_x(buf, x);
} else {
    do_something_about_them_errors();
}

在这种情况下,您不能再依赖x它在上一行中分配的值了。编译器可能已经移动了原来的位置x(重用它所在的寄存器或其他东西),所以进行比较的代码会在错误的位置查找。(你可以保存x到另一个变量,然后x在调用函数之前重新分配给其他变量,这可能会使问题更加明显)

在您的代码中,您可以将其编写为:

int conditional;
conditional = setjump(buf) != 0 ;
if(__builtin_expect( conditional, 1)) {
    // handle error
} else {
    // do action
}

而且我认为我们可以满足自己,分配变量的代码行conditional满足该要求。

于 2011-01-07T02:16:42.133 回答
0

但如果这是一个 GCC 扩展,我能否保证它适用于 GCC,因为它已经是非标准功能?我对它进行了测试,它似乎可以工作,但我不知道我需要做多少测试才能真正打破它。(我将 __builtin_expect 的调用隐藏在宏后面,该宏被定义为非 GCC 的无操作,因此对于其他编译器来说是完全合法的。)

你是对的, __builtin_expect 应该是其他编译器的宏无操作,所以结果仍然是定义的。

于 2011-01-07T02:35:34.650 回答