[cpp] view plaincopy
 
  1. char * s1 = "abcd";  
  2. s1[0] = 'm';//segment fault  

上面代码在gcc下编译运行将报段错误。

然而,

 

[cpp] view plaincopy
 
  1. char s1[] = "abcd";  
  2. s1[0] = 'm';  


这段代码则能够正确运行。其中包含的原理是char* 和 char[],在内存分配上的机制差异。

 

对于char *  s = "abcd";来说, 编译器会将字符串字面量当作常量数据处理,存放在.rodata段,这样以来,s将指向.rodata段中的某处内存,

因此对该段内存的修改会引起段错误。(另,printf等格式化字符串函数中的format string 如"%d"等也会被放在.rodata中。)

对于char s1[] = "abcd";来说,"abcd"是在栈上分配内存,使用mov指令直接将值写入栈上对应内存。

使用下面代码来验证上面的描述:

 

[cpp] view plaincopy
 
  1. #include <stdio.h>  
  2.   
  3. int main()  
  4. {  
  5.     char * s1 = "abcd";  
  6.     char s2[] = "efghef";  
  7. }  


查看汇编指令:

 

 

[plain] view plaincopy
 
  1. cString.o:     file format elf32-i386  
  2.   
  3. Contents of section .text:  
  4.  0000 5589e583 e4f083ec 1065a114 00000089  U........e......  
  5.  0010 44240c31 c0c70424 00000000 c7442405  D$.1...$.....D$.  
  6.  0020 65666768 66c74424 096566c6 44240b00  efghf.D$.ef.D$..  
  7.  0030 8b54240c 65331514 00000074 05e8fcff  .T$.e3.....t....  
  8.  0040 ffffc9c3                             ....              
  9. <span style="color:#3333FF;">Contents of section .rodata:  
  10.  0000 61626364 00                          abcd.  </span>           
  11. Contents of section .comment:  
  12.  0000 00474343 3a202855 62756e74 752f4c69  .GCC: (Ubuntu/Li  
  13.  0010 6e61726f 20342e35 2e322d38 7562756e  naro 4.5.2-8ubun  
  14.  0020 74753429 20342e35 2e3200             tu4) 4.5.2.       
  15.   
  16. Disassembly of section .text:  
  17.   
  18. 00000000 <main>:  
  19.    0:   55                      push   %ebp  
  20.    1:   89 e5                   mov    %esp,%ebp  
  21.    3:   83 e4 f0                and    $0xfffffff0,%esp  
  22.    6:   83 ec 10                sub    $0x10,%esp  
  23.    9:   65 a1 14 00 00 00       mov    %gs:0x14,%eax  
  24.    f:   89 44 24 0c             mov    %eax,0xc(%esp)  
  25.   13:   31 c0                   xor    %eax,%eax  
  26.   15:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)  
  27.  <span style="color:#3333FF;"> 1c:  c7 44 24 05 65 66 67    movl   $0x68676665,0x5(%esp)  
  28.   23:   68   
  29.   24:   66 c7 44 24 09 65 66    movw   $0x6665,0x9(%esp)</span>  
  30.   2b:   c6 44 24 0b 00          movb   $0x0,0xb(%esp)  
  31.   30:   8b 54 24 0c             mov    0xc(%esp),%edx  
  32.   34:   65 33 15 14 00 00 00    xor    %gs:0x14,%edx  
  33.   3b:   74 05                   je     42 <main+0x42>  
  34.   3d:   e8 fc ff ff ff          call   3e <main+0x3e>  
  35.   42:   c9                      leave    
  36.   43:   c3                      ret    

前面用蓝色标出部分为char*声明的字符串。后面蓝色标出部分位char[]字符串数组。

 

此外,对于函数如strcpy(s3,"abcd"),这样的调用,参数传入字符串常量的都是存储在.rodata段中的。