在gcc中使用内置函数__builtin_add_overflow_p

9
我在想如何使用这个函数,因为当我这样做时会出现错误:

#define INT_ADD_OVERFLOW_P(a, b) \
__builtin_add_overflow_p (a, b, (__typeof__ ((a) + (b))) 0);
#include <stdio.h>
#include <assert.h>
__int main()
{
    int x1 = -1073741826;
    int y1 = -1073741826;
    int z1 = x1+y1; 
    INT_ADD_OVERFLOW_P ( x1,  y1);
    printf("%d\n",z1);
    return 0;
}

编译输出:

gcc -c -Wall -D DEBUG  tempFile.c
gcc tempFile.o -o tempFile
Makefile:8: recipe for target 'tempFile' failed//new error after update

编译错误:

tempFile.c: In function ‘main’:
tempFile.c:10:1: warning: implicit declaration of function        ‘__builtin_add_overflow_p’ [-Wimplicit-function-declaration]
tempFile.o: In function `main':
tempFile.c:(.text+0x44): undefined reference to `__builtin_add_overflow_p'
collect2: ld returned 1 exit status
make: *** [tempFile] Error 1

这里是我想要使用的函数链接:

https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html

这是我正在使用的makefile:

compiler=gcc
CFLAGS=-c -Wall -D DEBUG 
programname=tempFile

all: $(programname)

$(programname): $(programname).o
    $(compiler) $(programname).o -o $(programname)

$(programname).o: $(programname).c
    $(compiler) $(CFLAGS) $(programname).c

clean:
    rm *o $(programname)

你使用的gcc版本是什么? - user253751
gcc(Ubuntu/Linaro 4.6.3-1ubuntu5)4.6.3 - Eagle
也尝试使用了Clang编译器。 - Eagle
这就是问题所在 - 这些内置函数是在较新的版本中添加的。(我想是5.x版本) - user253751
升级到Ubuntu 16.04以安装GCC 5,然后看看它的运行情况。 - Eagle
所以我升级到了16.04,运行gcc版本为5.4.0 20160609 - 得到了一个新的错误“Makefile:8: recipe for target 'tempFile' failed”,我将其添加到了问题中。我仍然会收到“undefined reference to __builtin_add_overflow_p”的错误。 - Eagle
3个回答

6

1

我发现如何使用内置函数。不再使用 __builtin_add_overflow_p,而是使用 __builtin_add_overflow。

#include <stdio.h>
#include <assert.h>

int main(void)
{
  int x1 = -1073741826;
  int y1 = -1073741826;
  int z1 = x1 + y1; 
  int temp;

  printf("%d\n", __builtin_add_overflow(x1, y1, &temp));
  if (__builtin_add_overflow(x1, y1, &temp)) {
    printf("overflow detected");
  }
  printf("%d\n", z1);

  return 0;
}

你能解释一下这两个调用之间的区别吗? - 2501
1
以p结尾的内置函数类似于__builtin_add_overflow、__builtin_sub_overflow和__builtin_mul_overflow。不同之处在于,以p结尾的函数不会将算术操作的结果存储在任何地方,并且最后一个参数不是指针,而是某个具有整数类型(枚举或布尔类型除外)的表达式。这里是整数类型的链接http://msdn.microsoft.com/en-us/library/exx3b86w%28v=vs.80%29.aspx - Eagle
1
我不明白为什么这会是一个答案。你的问题是如何使用一个函数,而你的解决方案却使用了另一个具有不同定义的函数?请将其作为评论放在你的问题下面,而不是说“不再是我的问题,但问题仍然存在”。 - Andreas

0

您还可以使用__builtin_add_overflow_p来实现类似于饱和加法的功能:

#define sadd(a, b)                                             \
    ({                                                         \
        __auto_type _a = (a);                                  \
        __auto_type _b = (b);                                  \
        __builtin_add_overflow_p(_a, _b, _a) ? _a : (_a + _b); \
    })

例子:

uint8_t foo = 253;

foo = sadd(foo, 1); // foo = 254
foo = sadd(foo, 1); // foo = 255
foo = sadd(foo, 1); // foo = 255

这里使用了 GCC 的一个扩展功能 Statement Expressions,并且 __auto_type 在这里解释 https://gcc.gnu.org/onlinedocs/gcc/Typeof.html

调用 __builtin_add_overflow_p 的意思是说,如果两个参数 ab 相加会产生溢出(第三个参数),返回 a 的原始值,否则返回 ab 相加的结果。

您也可以使用 __builtin_add_overflow,如果添加了第三个变量 c,并且如果结果没有溢出,则返回该变量,否则返回 a


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