c - Global variable vs macro expansion for string literal -
i'm trying understand of intricacies preprocessor , of c compiler (specifically, gnu gcc) , string literals. more efficient assign global variable string literal occupies 1 place in memory vs using #define
preprocessor directive?
as in example, string literal on place in memory , accessed several times:
#include <stdio.h> #include <string.h> char output[20] = "hello, world!!!"; int main (){ printf("%s %d characters long.\n", output, strlen(output)); return 0; }
vs doing preprocessor:
#include <stdio.h> #include <string.h> #define output "hello, world!!!" int main (){ printf("%s %d characters long.\n", output, (int) strlen(output)); return 0; }
which translates as:
#include <stdio.h> #include <string.h> #define output "hello, world!!!" int main (){ printf("%s %d characters long.\n", "hello, world!!!", (int) strlen("hello, world!!!")); return 0; }
what i'm asking in last 2 examples example using preprocessor, compiler have 2 separate instances of "hello, world!!!" in 2 separate memory locations or compiler smart enough make 1 memory location?
if 2 separate memory locations, isn't more resource-friendly use global variable rather macro expansion program constants?
your compiler should smart enough store 1 instance of string. can verify checking assembly outputs programs.
for example, using gcc:
assume first example called "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 %d characters long.\n" .text .globl main .type main, @function main: // more code...
assume preprocessor example called "preproc.c".
gcc -wall -s preproc.c .file "preproc.c" .section .rodata .lc0: .string "%s %d characters long.\n" .lc1: .string "hello, world!!!" .text .globl main .type main, @function main: // more code...
in both cases, 1 copy of "hello, world!!!" , "%s %d characters long.\n" exist. in first example, have save space 20 characters because code has modifiable array. if changed this
char output[20] = "hello, world!!!";
to
const char * const output = "hello, world!!!";
you get:
.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 %d characters long.\n" .text .globl main .type main, @function main: // more code...
now saving space pointer , string.
which way better negligible in situation, though recommend using preprocessor scope of strings stays within main function.
both emit identical code optimizations.
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 %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 %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
looking @ both main
functions, can see instructions identical.
Comments
Post a Comment