简体   繁体   English

printf 是 C 中的 static function 吗?

[英]Is printf a static function in C?

I'm pretty new to C, and I know that static functions can only be used within the same object file.我是 C 的新手,我知道 static 函数只能在同一个 object 文件中使用。 Something that still confuses me though, is how if I hover over a call to printf in my IDE it tells me that printf is a static function, when I can perfectly use printf in multiple object files without any problems? Something that still confuses me though, is how if I hover over a call to printf in my IDE it tells me that printf is a static function, when I can perfectly use printf in multiple object files without any problems? Why is that?这是为什么?




Edit : I'm using Visual Studio Code the library is stdio.h and compiling using GCC编辑:我正在使用 Visual Studio Code 库是 stdio.h 并使用 GCC 进行编译

#include <stdio.h>
int main()
{
  printf("Hello, world!");
  return 0;
}

Hovering over printf would give that hint将鼠标悬停在 printf 上会给出提示

Edit 2 : if static inline functions are different from inline functions how so?编辑 2 :如果 static 内联函数与内联函数不同怎么办? I don't see how making a function inline would change the fact that it's only accessible from the same translation unit我看不出制作 function 内联会如何改变只能从同一个翻译单元访问的事实

Edit 3 : per request, here's the definition of printf in the stdio.h header编辑 3 :根据请求,这是stdio.h header 中printf的定义

__mingw_ovr
__attribute__((__format__ (gnu_printf, 1, 2))) __MINGW_ATTRIB_NONNULL(1)
int printf (const char *__format, ...)
{
  int __retval;
  __builtin_va_list __local_argv; __builtin_va_start( __local_argv, __format );
  __retval = __mingw_vfprintf( stdout, __format, __local_argv );
  __builtin_va_end( __local_argv );
  return __retval;
}

screenshot of the printf definition in my IDE我的 IDE 中 printf 定义的截图

Thanks for all the updates.感谢所有更新。 Your IDE is showing you implementation details of your C library that you're not supposed to have to worry about.您的 IDE 向您展示了您不必担心的 C 库的实现细节。 That is arguably a bug in your IDE but there's nothing wrong with the C library.这可以说是您的 IDE 中的错误,但 C 库没有任何问题。

You are correct to think that a function declared static is visible only within the translation unit where it is defined.您认为声明为static的 function 仅在定义它的翻译单元内可见是正确的。 And that is true whether or not the function is also marked inline .无论 function 是否也被标记为inline都是如此。 However , this particular static inline function is defined inside stdio.h , so every translation unit that includes stdio.h can see it.然而,这个特殊static inline function 是stdio.h中定义的,所以每个包含stdio.h的翻译单元都可以看到它。 (There is a separate copy of the inline in each TU. This is technically a conformance violation since, as chux surmises, it means that &printf in one translation unit will not compare equal to &printf in another. However, this is very unlikely to cause problems for a program that isn't an ISO C conformance tester.) (每个 TU 中都有一个单独的内联副本。从技术上讲,这违反了一致性,因为正如 chux 推测的那样,这意味着一个翻译单元中的&printf &printf不会与另一个翻译单元中的 &printf 进行比较。然而,这不太可能导致不是 ISO C 一致性测试程序的程序的问题。)

As "Adrian Mole" surmised in the comments on the question, the purpose of this inline function is, more or less, to rewrite正如“Adrian Mole”在对该问题的评论中推测的那样,此内联 function 的目的或多或少是重写

printf("%s %d %p", string, integer, pointer);

into进入

fprintf(stdout, "%s %d %p", string, integer, pointer);

(All the stuff with __builtin_va_start and __mingw_vfprintf is because of limitations in how variadic functions work in C. The effect is the same as what I showed above, but the generated assembly language will not be nearly as tidy.) (所有带有__builtin_va_start__mingw_vfprintf的东西都是因为可变参数函数在 C 中的工作方式的限制。效果与我上面展示的相同,但生成的汇编语言不会那么整洁。)


Update 2022-12-01: It's worse than "the generated assembly language will not be nearly as tidy". 2022-12-01 更新:它比“生成的汇编语言不会那么整洁”更糟糕。 I experimented with all of the x86 compilers supported by godbolt.org and none of them will inline a function that takes a variable number of arguments, even if you try to force it.我对 godbolt.org 支持的所有x86编译器进行了试验,没有一个会内联一个 function,它采用可变编号 arguments,即使你试图强制它。 Most silently ignore the force-inlining directive;大多数默默地忽略 force-inlining 指令; GCC gets one bonus point for actually saying it refuses to do this: GCC 因实际表示拒绝这样做而获得一分奖励积分:

test.c:4:50: error: function ‘xprintf’ can never be inlined 
    because it uses variable argument lists

In consequence, every program compiled against this version of MinGW libc, in which printf is called from more than one .c file, will have multiple copies of the following glob of assembly embedded in its binary.因此,针对此版本的 MinGW libc 编译的每个程序(其中printf从多个.c文件调用)将在其二进制文件中嵌入以下程序集的多个副本。 This is bad just because of cache pollution;这很糟糕,只是因为缓存污染; it would be better to have a single copy in the C library proper -- which is exactly what printf normally is.最好在 C 库中有一个副本——这正是printf通常的样子。

printf:
        mov     QWORD PTR [rsp+8], rcx
        mov     QWORD PTR [rsp+16], rdx
        mov     QWORD PTR [rsp+24], r8
        mov     QWORD PTR [rsp+32], r9
        push    rbx
        push    rsi
        push    rdi
        sub     rsp, 48
        mov     rdi, rcx
        lea     rsi, QWORD PTR f$[rsp+8]
        mov     ecx, 1
        call    __acrt_iob_func
        mov     rbx, rax
        call    __local_stdio_printf_options
        xor     r9d, r9d
        mov     QWORD PTR [rsp+32], rsi
        mov     r8, rdi
        mov     rdx, rbx
        mov     rcx, QWORD PTR [rax]
        call    __stdio_common_vfprintf
        add     rsp, 48
        pop     rdi
        pop     rsi
        pop     rbx
        ret     0

(Probably not exactly this assembly, this is what godbolt's "x64 MSVC 19.latest" produces with optimization option /O2 , godbolt doesn't seem to have any MinGW compilers. But you get the idea.) (可能不完全是这个程序集,这是 godbolt 的“x64 MSVC 19.latest”使用优化选项/O2生成的,godbolt 似乎没有任何 MinGW 编译器。但你明白了。)

__mingw_ovr is normally defined as __mingw_ovr通常定义为

#define __mingw_ovr static __attribute__ ((__unused__)) __inline__ __cdecl

It appears that this definition of printf is a violation of the C standard.看起来printf的定义违反了 C 标准。 The standard says标准说

7.1.2 Standard headers 7.1.2 标准标题
6 Any declaration of a library function shall have external linkage 6 库function的任何声明都要有外部链接

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

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