您的编译器应该足够聪明,可以存储一个字符串实例。您可以通过检查程序的汇编输出来验证这一点。
例如,使用 GCC:
假设您的第一个示例名为“global.c”。
gcc -Wall -S global.c
.file "global.c"
.globl OUTPUT
.data
.align 16
.type OUTPUT, @object
.size OUTPUT, 20
OUTPUT:
.string "Hello, world!!!"
.zero 4
.section .rodata
.LC0:
.string "%s is %d characters long.\n"
.text
.globl main
.type main, @function
main:
// More code...
假设您的预处理器示例名为“preproc.c”。
gcc -Wall -S preproc.c
.file "preproc.c"
.section .rodata
.LC0:
.string "%s is %d characters long.\n"
.LC1:
.string "Hello, world!!!"
.text
.globl main
.type main, @function
main:
// More code...
在这两种情况下,只有一份“Hello, world!!!” 并且“%s 的长度为 %d 个字符。\n”存在。在第一个示例中,您必须为 20 个字符节省空间,因为您的代码有一个可修改的数组。如果你改变了这个
char OUTPUT[20] = "Hello, world!!!";
至
const char * const OUTPUT = "Hello, world!!!";
你会得到:
.file "global.c"
.globl OUTPUT
.section .rodata
.LC0:
.string "Hello, world!!!"
.align 8
.type OUTPUT, @object
.size OUTPUT, 8
OUTPUT:
.quad .LC0
.LC1:
.string "%s is %d characters long.\n"
.text
.globl main
.type main, @function
main:
// More code...
现在您只为指针和字符串节省空间。
在这种情况下,哪种方式更好可以忽略不计,但我建议使用预处理器,以便字符串的范围保持在主函数内。
两者都发出几乎相同的优化代码。
带有 ( ) 的 Global.c const char * const OUTPUT
:
gcc -Wall -O3 -S global.c
.file "global.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "Hello, world!!!"
.LC1:
.string "%s is %d characters long.\n"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB44:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $15, %ecx
movl $.LC0, %edx
movl $.LC1, %esi
movl $1, %edi
xorl %eax, %eax
call __printf_chk
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE44:
.size main, .-main
.globl OUTPUT
.section .rodata
.align 8
.type OUTPUT, @object
.size OUTPUT, 8
OUTPUT:
.quad .LC0
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",@progbits
Preproc.c
gcc -Wall -O3 -S preproc.c
.file "preproc.c"
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "Hello, world!!!"
.LC1:
.string "%s is %d characters long.\n"
.section .text.startup,"ax",@progbits
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB44:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $15, %ecx
movl $.LC0, %edx
movl $.LC1, %esi
movl $1, %edi
xorl %eax, %eax
call __printf_chk
xorl %eax, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE44:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",@progbits
查看这两个main
函数,您可以看到说明是相同的。