简体   繁体   English

为什么gcc不调用abs函数?

[英]Why doesn't gcc call abs function?

I have some C code我有一些 C 代码

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

int32_t abs(int32_t x) {

        int32_t mask = (x >> 31);
        printf("mask is %d\n",mask);
        return (x + mask) ^ mask;

}
int main(int argc, char *argv[])
{
        int32_t i=-5;
        printf("%d\n",abs(i));

        return 0;
}

and I compile it with GCC.我用 GCC 编译它。

gcc -O0 -S -masm=intel gcc -O0 -S -masm=intel

The asm code is in https://pastebin.com/4TGpSsdd asm 代码在https://pastebin.com/4TGpSsdd

Why doesn't gcc call abs function but clang do.为什么gcc 不调用abs 函数而clang 调用。

The program doesn't call abs function and该程序不调用 abs 函数和

execute code 「printf("mask is %d\\n",mask);」执行代码「printf("mask is %d\\n",mask);」

My gcc version:我的 gcc 版本:

gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4 gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4

Is this a gcc bug?这是一个gcc错误吗?

abs is a builtin in GCC, but Clang replaces builtins with calls to their respective library functions. abs是一种内置在GCC,但锵取代建宏通过调用各自的库函数。

To fix this, you can rename your function (which is recommended; see below for the reasoning) you can compile your code using -fno-builtin-abs , or you can mark your function as static .要解决此问题,您可以重命名您的函数(建议这样做;推理见下文)您可以使用-fno-builtin-abs编译您的代码,或者您可以将您的函数标记为static

Here's a quote from the linked page:这是链接页面的引用:

The ISO C90 functions abort , abs , acos , [...] and vsprintf are all recognized as built-in functions unless -fno-builtin is specified (or -fno-builtin- function is specified for an individual function).在ISO C90功能abortabsacos ,[...]和vsprintf被除非所有公认的内建函数-fno-builtin指定(或-fno-builtin- function为单个功能被指定)。 All of these functions have corresponding versions prefixed with __builtin_ .所有这些函数都有以__builtin_为前缀的相应版本。

The C standard states that redefining library functions with external is undefined behavior (C11 §7.1.3 1): C 标准指出,使用外部重新定义库函数是未定义的行为(C11 §7.1.3 1):

All identifiers with external linkage in any of the following subclauses (including the future library directions) and errno are always reserved for use as identifiers with external linkage.以下任何子条款(包括未来的库方向)和errno中的所有具有外部链接的标识符始终保留用作具有外部链接的标识符。

If you define abs as static , the call will not be removed.如果您将abs定义为static ,则不会删除该调用。

There is a function int abs(int x) in stdlib.h . stdlib.h有一个函数int abs(int x)

You need to rename your function.您需要重命名您的函数。

  1. do not use standard function name.不要使用标准函数名。 Many functions (including abs ) are known well to the gcc compiler.许多函数(包括abs )对于 gcc 编译器来说是众所周知的。 They are called built-ins.它们被称为内置函数。 So compiler knows what this function does and in many cases it does not have to call it.所以编译器知道这个函数做什么,而且在很多情况下它不必调用它。

If you rename it - it will genrate the call with the -O0 https://godbolt.org/z/dLg26U如果您重命名它 - 它将使用 -O0 https://godbolt.org/z/dLg26U生成呼叫

if you want to have it called if you enable optimizations you need to tell the compiler to do not inline it.如果你想在启用优化的情况下调用它,你需要告诉编译器不要内联它。 https://godbolt.org/z/aHaEik https://godbolt.org/z/aHaEik

 int32_t __attribute__((noinline)) myabs(int32_t x) {

Is this a gcc bug?这是一个gcc错误吗?

No.不。

abs is a function defined in the C standard, it's prototype is provided as int abs (int) by #include <stdlib.h> . abs是 C 标准中定义的函数,它的原型由#include <stdlib.h>提供为int abs (int)

However, even without including that header, gcc has build-in knowledge about abs and knows what it is supposed to do.然而,即使不包含该头文件,gcc 也有关于abs内置知识,并且知道它应该做什么。 This applies to hosted C, which most users are using.这适用于大多数用户正在使用的托管 C。

In non-hosted C however, the compiler must not make any assumptions wrt the semantics of functions declared in the standard headers.然而,在非托管 C 中,编译器不能对标准头文件中声明的函数的语义做出任何假设。 In gcc, you get non-hested resp.在 gcc 中,您会得到不受限制的响应。 freestanding by -freestanding .独立式-freestanding

In addition, even without optimization turned on ( -O0 ), gcc will fold constants.此外,即使没有开启优化( -O0 ),gcc 也会折叠常量。 This is because in这是因为在

int x = 1 + 2;

you cannot do the initialization at run-time for x in static storage – as opposed to C++ which could initialize that at run-time in principle.您不能在运行时为静态存储中的x进行初始化 - 与 C++ 相反,C++ 原则上可以在运行时对其进行初始化。 In you case在你的情况下

abs (-5)

is folded to 5 .被折叠到5

As you very likely do not want to use -ffreestanding , you can use -fno-builtin-abs to take away built-in knowledge about abs , same for many other functions.由于您很可能不想使用-ffreestanding ,您可以使用-fno-builtin-abs-ffreestanding有关abs内置知识,这对于许多其他功能也是如此。 Even with -fno-builtin-abs option, you can use __builtin_abs in your code if you prefer the optimized version of absolute value computation and no libcall to libc.a / libc.so .即使使用-fno-builtin-abs选项,如果您更喜欢绝对值计算的优化版本并且没有对libc.a / libc.so libcall,您也可以在代码中使用__builtin_abs


Addendum ad freestanding due to a comment: C99 §4 Conformance, says:由于评论而独立的附录广告:C99 §4 一致性,说:

  1. The two forms of conforming implementation are hosted and freestanding.两种形式的一致性实现是托管和独立的。 A conforming hosted implementation shall accept any strictly conforming program.符合要求的托管实施应接受任何严格符合要求的程序。 A conforming freestanding implementation shall accept any strictly conforming program that does not use complex types and in which the use of the features specified in the library clause (clause 7) is confined to the contents of the standard headers <float.h> , <iso646.h> , <limits.h> , <stdarg.h> , <stdbool.h> , <stddef.h> , and <stdint.h> .符合标准的独立实现应接受任何不使用复杂类型的严格符合程序,并且其中库条款(第 7 条)中指定的功能的使用仅限于标准头文件<float.h><iso646.h><limits.h><stdarg.h><stdbool.h><stddef.h><stdint.h>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM