2009-11-20 85 views
14
char数组和指针用C

所以,我有下面的程序:分割故障原因在Linux

int main(){ 
    char* one = "computer"; 
    char two[] = "another"; 
    two[1]='b'; 
    one[1]='b'; 
    return 0; 
} 

它出现segfaults上这是有意义的行“一个[1] =‘B’”,因为存储器“one”指针必须位于只读存储器中。然而,问题是为什么不行“two [1] ='b'”段错误?查看gcc的汇编输出:

.file "one.c" 
     .section  .rodata 
.LC0: 
     .string "computer" 
.LC1: 
     .string "another" 
     .text 
.globl main 
     .type main, @function 
main: 

我们看到两个字符串都位于rodata节中,因此它们是只读的。那么为什么线“two [1] ='b'没有段错误?

+0

也看到了不同,但相关的问题http://stackoverflow.com/questions/ 1770067 /定义指针到静态字符串/ 1770067#1770067 – 2009-11-20 20:43:14

回答

35

one直接指向位于只读页面的字符串另一方面,two是一个在堆栈上分配的数组并用一些常量数据初始化,在运行时,可执行文件的只读部分中的字符串将被复制到堆栈中,您正在修改的是该堆栈中该字符串的副本,而不是只读存储器页面。

在较高的水平角度,从语言角度,"abcd"const char*类型和表达式不char*。因此,修改由不确定的行为这样的表达式的结果指出的值。该语句char* one = "something";仅将指向字符串的指针存储在变量中(不安全,因为它正在丢弃const修饰符)。 char two[] = "something";是完全不同的。它实际上是声明一个数组并初始化它,就像int a[] = {1,2,3};。这里引号中的字符串是初始化表达式。

+3

哇...我已经在C编程了大约5年,现在我不知道'char []'做了一个常量数据的副本。我一直认为''''是写'*'的更好的方法。谢谢! +1 – Earlz 2009-11-20 20:39:52

+3

我经常写'char str [] = {“Something”};'试图使关联更清晰。 – LnxPrgr3 2009-11-20 21:01:30

+0

@ Mehrdad:水晶般清澈! :) – 2012-06-20 17:20:06

1

您在rodata部分看到的“另一个”将在数组two中被初始化时被复制。另一方面,字符串“computer”的地址将被分配给一个。

因此,one指向一个只读段(因此写入时段错误),而two将被分配到堆栈,然后将“另一个”复制到它。

0

第二种形式通过复制文字字符串来创建数组。

它等效于:

char two[] = {'a', 'n', 'o', 't', 'h'. 'e', r', '\0'}; 

可以初始化字符数组变量,如

char c = 'a'; 
char two[] = {'a', 'n', c, '\0'};