整数溢出测试运算符?(&+)

3
这个问题可能只是对操作符理解错误的另一种情况。但是不久前,我看到有人在推特上发帖说,在C语言中可以使用一个运算符来检查整数溢出。也就是 &+(和加号)运算符,可以像这样简单地使用:
#include <stdio.h>
#include <stdint.h>

int main()
{
    uint32_t x, y;

    x = 0xFFFFFFFF;
    y = 1;

    if (x &+ y) {
        printf("Integer overflow!\n");
    } else {
        printf("No overflow\n");
    }

    return 0;
}

我发现这段代码的工作方式符合预期,使用以下参数编译时,GCC 6没有抛出任何警告或错误:gcc -Wall -Wextra -Werror of.c

但是奇怪的是,我还没有找到关于这个运算符的任何文档,并且我从未在任何地方看到过它的使用。请问有人可以解释一下这是如何工作的吗?


1
并不真正测试溢出,但除此之外,它是一个完全良好的运算符(或两个)。 - n. m.
1
无符号整数不会溢出,而是会循环,有符号整数在溢出时会引发未定义的行为。那一行代码没有任何合理的作用。甚至不要听那些模糊的 YouTube 视频、博客或推特帖子。 - too honest for this site
1
颤动的短信不适合作为C语言编程教材的来源。 - Martin James
我不确定你读了什么,但你确定没有读到关于Swift的内容吗?Swift确实有&+ - Antti Haapala -- Слава Україні
@AnttiHaapala 我找到了那条推文。它明确是针对C语言的。我不知道,可能是我被愚弄了。https://twitter.com/Xeeynamo/status/745690790798712832 - user966939
显示剩余4条评论
3个回答

8
表达式
x &+ y

被解析为

x & (+y)

使用一元正运算符(+),该运算符在这种情况下没有效果,只返回y。 这意味着该表达式等同于
x & y

该代码片段 并没有 检测整数溢出,只是检查x和y是否有任何共同的位。试着将x和y改为1,看看会发生什么;即使不会发生溢出,它也会报告溢出。


@StoryTeller:嗯,无论何时操作数参与算术表达式,都应该发生提升吧? - Matteo Italia
@templatetypedef 哎呀!我想我应该测试更多的值。一元加运算符不是我听说很多次的,当我谷歌“单个加运算符”时,我没有看到任何明显的东西,哈哈。这个名字听起来很熟悉。感谢您的答案! - user966939
1
@StoryTeller,你从哪里得到的这个信息?在C11中,它说“通常的算术转换会被执行”。整数提升是该过程的一部分。 - Jens Gustedt
@JensGustedt - 我知道这不是规范,但仍然适用。 - StoryTeller - Unslander Monica
2
@StoryTeller,你理解错了。Nsz也说“通常算术转换的一部分”。这是C标准中的一个精确技术术语,C标准明确规定了它适用的范围。位运算也包括在其中。 - Jens Gustedt
@JensGustedt - 是的,在按位与的描述中似乎确实是这样说的。哦,那么一元加号也没有用了。 - StoryTeller - Unslander Monica

3
那可能是个玩笑,不存在 &+ 操作符。如果你写 x&+y,它会被解释为 x & (+y),其中 & 是二进制按位与操作符,+ 是一元加法操作符,除了可能执行算术提升之外什么也不做(例如,如果 y 是 short 或 char 类型,则会被提升为 int;在你的情况下什么也不做)。无论如何,这个表达式实际上没有严格的关系来检查溢出。

1

您可能需要使用__builtin_add_overflow(完全通用,但不太常见)或__builtin_uadd_overflow(适用于unsigned int)。

#include <stdio.h>
#include <stdint.h>

int main()
{
    uint32_t x, y;

    x = 0xFFFFFFFF;
    y = 1;

    if (__builtin_add_overflow(x, y, &x)) {
        printf("Integer overflow!\n");
    } else {
        printf("No overflow\n");
    }

    return 0;
}

据我所知,在gcc/clang中没有内置的检查运算符,&+仅是&后跟一元+
个人正在使用一个包装器宏来使用这些内置函数,如果它们可用,否则会回退到一个无内置函数的解决方案,该解决方案受到可用于溢出检查的代码的启发。https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接