[英]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 向您展示了您不必擔心的 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.