编译器中格式说明符的工作机制:以C语言%s为例解析
%s) Work in C: Compilation & Runtime Breakdown Great question! Let’s walk through exactly how format specifiers such as %s operate, using your examples to clarify the compilation step and then diving into the runtime logic that makes the substitution happen.
Compilation Phase: What the Compiler Does (Not What You Might Think)
First, let’s clear up a common misconception: the compiler does NOT replace %s with your actual string during compilation. Instead, it handles two key tasks:
Storing string literals in memory
- Any string literal in your code (like
"Hello %s"or"World !") gets packed into a read-only data section of the executable (your assembly examples show this as.LC0and.LC1, which are compiler-generated labels for these string locations). The.stringassembly directive just writes the ASCII bytes of the string into memory, including the literal%scharacters—no substitution happens here. - For your example, the assembly output:
Simply means.LC0: .string "World !" .LC1: .string "Hello %s""World !"lives at the memory address labeled.LC0, and"Hello %s"lives at.LC1.
- Any string literal in your code (like
Preparing the
printfcall- The compiler generates assembly code to pass the addresses of these strings as arguments to
printf. Depending on the system’s calling convention (e.g., x86-64 System V or x86 cdecl), it’ll either load these addresses into registers or push them onto the stack, then issue a call to theprintffunction from the C standard library. - The compiler doesn’t parse the format string’s
%shere—it just treats it as part of the first argument’s data.
- The compiler generates assembly code to pass the addresses of these strings as arguments to
Runtime Phase: How printf Handles %s
The actual magic of replacing %s with your string happens when the program runs, inside the printf function itself. Here’s the step-by-step:
Traversing the format string
printfstarts at the address of the format string (.LC1in your example) and reads each character one by one:- When it hits regular characters (like
H,e,l,l,o,), it writes them directly to standard output. - When it encounters a
%character, it knows to look at the next character to determine the format specifier.
- When it hits regular characters (like
Processing
%sspecifically- When it sees
safter the%,printfknows it needs to output a null-terminated string. It uses the macros from<stdarg.h>(likeva_arg) to fetch the next argument from the variable argument list—which is the address of"World !"(.LC0). printfthen starts reading characters from that address, writing each one to standard output, until it hits the null terminator (\0) that marks the end of the string.
- When it sees
Finishing up
- After processing the
%sand the rest of the format string,printfreturns the number of characters written, and your program continues execution.
- After processing the
Putting It All Together With Your Example
For your code:
printf("Hello %s", "World !");
- Compilation: The compiler stores
"Hello %s"at.LC1and"World !"at.LC0, then sets up the call toprintfwith these two addresses as arguments. - Runtime:
printfoutputs"Hello ", then sees%s, fetches the address of"World !", outputs those characters, resulting in the final output:Hello World !.
内容的提问来源于stack exchange,提问作者Lasan Nishshanka

