先来意淫一下
群里大神分享了一个Stack Overflow
上字符数组与字符串指针数组的差别
的问答,感觉回答中说的都不太到我的心坎里,故也来凑下热闹。以下面代码为样例,从以下两个层次来说:
1 2 3 4 5 6 7 8 9 10 11 12
| #include <stdio.h> #include <stdlib.h>
int main(int argc, char * argv[]) {
char * p = "good morning"; char h[] = "hello world"; printf("%s\n",p); printf("%s\n",h); return 0; }
|
char * p = "good morning";
char h[] = "hello world";
类型(语义)
从c语言种对两种类型使用时的感受来说,存在char h[]
<==>
char * const h
这种等价关系。对于程序员来说,使用
时候的差别也主要体现在
char * const h
中的多出的const
的差别。
内存分配(语义的实现)
两种类型表示的语义不同,其值所占的底层内存位置、生存时间也就不一样。
函数在底层实现的时候放在栈上的,运行结束的时候,栈会被回收,函数局部变量的值所占用的内存编译器会直接回收。
指针指向的内容表示指针指向的内存由程序员管理申请、释放等工作。
故指针的值在栈上,字符字面量填充的数组也在栈上,指针指向的内容分配在堆上。
另外指针在底层指令上会多一次访存
。
看看到底汇编长啥样
总结
总结据说该放最后,但我还是把它提上来了。:)
原先我还担心高级别的优化,会把我上面的代码,堆上的也优化到栈上,故编译了两个优化级别的,其实并没有。反而都是验证了我上面的两个想法。
核心代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
subl $32, %esp
movl $LC0, (%esp)
movl $1819043176, 20(%esp) movl $1870078063, 24(%esp) movl $6581362, 28(%esp)
call _puts
leal 20(%esp), %eax movl %eax, (%esp) call _puts
|
环境信息
1 2 3 4 5 6 7 8 9
| - -. . ....-.
..-.. ----- -- -- ---- -- --- ---,++,,-++,, --- --- --- --- ---- ------ ---- ---- --- --- --- --- ..-.. ----- -- -- ---- -- --- ---,++,,-++,, --- --- --- --- ---- ------ ---- ---- ---- --- --- --- ---
..
|
二级优化 -O2
gcc -m32 -S -O2 Untitled1.c -o 2.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| .file "Untitled1.c" .def ___main; .scl 2; .type 32; .endef .section .rdata,"dr" LC0: .ascii "good morning\0" .section .text.unlikely,"x" LCOLDB1: .section .text.startup,"x" LHOTB1: .p2align 4,,15 .globl _main .def _main; .scl 2; .type 32; .endef _main: LFB21: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 andl $-16, %esp subl $32, %esp call ___main movl $LC0, (%esp) movl $1819043176, 20(%esp) movl $1870078063, 24(%esp) movl $6581362, 28(%esp) call _puts leal 20(%esp), %eax movl %eax, (%esp) call _puts xorl %eax, %eax leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc LFE21: .section .text.unlikely,"x" LCOLDE1: .section .text.startup,"x" LHOTE1: .ident "GCC: (GNU) 5.3.0" .def _puts; .scl 2; .type 32; .endef
|
未优化 -O0
gcc -m32 -S -O0 Untitled1.c -o 2.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| .file "Untitled1.c" .def ___main; .scl 2; .type 32; .endef .section .rdata,"dr" LC0: .ascii "good morning\0" .text .globl _main .def _main; .scl 2; .type 32; .endef _main: LFB12: .cfi_startproc pushl %ebp .cfi_def_cfa_offset 8 .cfi_offset 5, -8 movl %esp, %ebp .cfi_def_cfa_register 5 andl $-16, %esp subl $32, %esp call ___main movl $LC0, 28(%esp) movl $1819043176, 16(%esp) movl $1870078063, 20(%esp) movl $6581362, 24(%esp) movl 28(%esp), %eax movl %eax, (%esp) call _puts leal 16(%esp), %eax movl %eax, (%esp) call _puts movl $0, %eax leave .cfi_restore 5 .cfi_def_cfa 4, 4 ret .cfi_endproc LFE12: .ident "GCC: (GNU) 5.3.0" .def _puts; .scl 2; .type 32; .endef
|