簡體   English   中英

printf 是 C 中的 static function 嗎?

[英]Is printf a static function in C?

我是 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? 這是為什么?




編輯:我正在使用 Visual Studio Code 庫是 stdio.h 並使用 GCC 進行編譯

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

將鼠標懸停在 printf 上會給出提示

編輯 2 :如果 static 內聯函數與內聯函數不同怎么辦? 我看不出制作 function 內聯會如何改變只能從同一個翻譯單元訪問的事實

編輯 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;
}

我的 IDE 中 printf 定義的截圖

感謝所有更新。 您的 IDE 向您展示了您不必擔心的 C 庫的實現細節。 這可以說是您的 IDE 中的錯誤,但 C 庫沒有任何問題。

您認為聲明為static的 function 僅在定義它的翻譯單元內可見是正確的。 無論 function 是否也被標記為inline都是如此。 然而,這個特殊static inline function 是stdio.h中定義的,所以每個包含stdio.h的翻譯單元都可以看到它。 (每個 TU 中都有一個單獨的內聯副本。從技術上講,這違反了一致性,因為正如 chux 推測的那樣,這意味着一個翻譯單元中的&printf &printf不會與另一個翻譯單元中的 &printf 進行比較。然而,這不太可能導致不是 ISO C 一致性測試程序的程序的問題。)

正如“Adrian Mole”在對該問題的評論中推測的那樣,此內聯 function 的目的或多或少是重寫

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

進入

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

(所有帶有__builtin_va_start__mingw_vfprintf的東西都是因為可變參數函數在 C 中的工作方式的限制。效果與我上面展示的相同,但生成的匯編語言不會那么整潔。)


2022-12-01 更新:它比“生成的匯編語言不會那么整潔”更糟糕。 我對 godbolt.org 支持的所有x86編譯器進行了試驗,沒有一個會內聯一個 function,它采用可變編號 arguments,即使你試圖強制它。 大多數默默地忽略 force-inlining 指令; GCC 因實際表示拒絕這樣做而獲得一分獎勵積分:

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

因此,針對此版本的 MinGW libc 編譯的每個程序(其中printf從多個.c文件調用)將在其二進制文件中嵌入以下程序集的多個副本。 這很糟糕,只是因為緩存污染; 最好在 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

(可能不完全是這個程序集,這是 godbolt 的“x64 MSVC 19.latest”使用優化選項/O2生成的,godbolt 似乎沒有任何 MinGW 編譯器。但你明白了。)

__mingw_ovr通常定義為

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

看起來printf的定義違反了 C 標准。 標准說

7.1.2 標准標題
6 庫function的任何聲明都要有外部鏈接

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM