2009-10-30 33 views
1

为什么当我使用下面的方法,将用于所有字符转换成字符串为大写,不同的字符串初始化会产生不同的行为?

while (*postcode) { 
    *postcode = toupper(*postcode); 

    postcode++; 
} 

使用下面的参数作品,

char wrong[20]; 
strcpy(wrong, "la1 4yt"); 

但以下,没有按不,尽管他们是一样的?

char* wrong = "la1 4yt"; 

我的程序崩溃试图写入非法地址(段错误,我猜)。这不是malloc ing的问题吗?不是无效的?它不应该是...

通过调试,我注意到它试图分配第一个字符作为其大写崩溃。

任何帮助表示赞赏!

+1

http://stackoverflow.com/questions/1614723/why-is-this-c-code-causing-a-segmentation-fault/1614739#1614739 – AnT 2009-10-30 00:29:47

+1

+1避免'* postcode = toupper(* postcode ++) ;''或同样不好的'*邮编++ = toupper(*邮编);':) – pmg 2009-10-30 00:55:31

+1

为了大声哭泣......这个问题每周至少会弹出两次。 – ephemient 2009-10-30 01:03:48

回答

5
char* wrong = "la1 4yt"; 

声明一个指针,指向一个字符串常量。常量不能被修改,这就是为什么你的代码崩溃。如果你写的更迂腐

const char* wrong = "la1 4yt"; // Better 

然后编译器会发现错误。只要你声明一个字符串文字的指针,而不是创建一个数组,你应该可以这样做。

另一方面,这分配了20个字符的读/写存储空间,因此写入空间很好。

char wrong[20]; 

如果你想初始化它到上面的字符串,你可以这样做然后将被允许改变它。

char wrong[20] = "la1 4yt"; // Can be modified 
char wrong[] = "la1 4yt"; // Can be modified; only as large as required 
+0

有没有办法只有内存需要保存“la1 4yt”将分配在初始化[可变]字符串?在数组中声明它对我来说太冗长了。 – 2009-10-30 00:19:19

+0

当然,您可以省略大小并让编译器计算它。 – 2009-10-30 00:21:45

2
char * whatever = "some cont string"; 

是只读的。

2

在第二个变体中,"la1 4yt"是一个常数,因此处于只读段。只有指向常量的指针(wrong)是可写的。这就是为什么你得到段错误。然而,在第一个例子中,一切都是可写的。

这一次可能是有趣:http://eli.thegreenplace.net/2009/10/21/are-pointers-and-arrays-equivalent-in-c/

+0

欢呼的链接 – 2009-10-30 00:15:51

+0

请参阅http://c-faq.com/aryptr/aryptrequiv.html和http://c-faq.com/aryptr/aryptrparam.html和http://c-faq.com/aryptr /arypbref.html – 2009-10-30 01:19:08

1

当你

char wrong[20] = "la1 4yt"; 

编译器拷贝字符串的文字{'l', 'a', '1', ' ', '4', 'y', 't', '\0'}wrong阵列的相应元素中的元素;当你做

char *wrong = "la1 4yt"; 

编译器分配给wrong字符串常量的地址。

字符串文字char[](字符数组),不const char[] ...但你不能改变他们!从标准

报价:

6.4.5 String literals 
6 It is unspecified whether these arrays are distinct provided 
    their elements have the appropriate values. If the program 
    attempts to modify such an array, the behavior is undefined. 

当我使用一个字符串初始化char *,我平时也告诉编译器我不会改变该字符串的内容文字中加入一个const到定义。

const char *wrong = "la1 4yt"; 

编辑

假设你有

char *test1 = "example test"; 
char *test2 = "test"; 

,编译器创建1单一字符串字面量和使用的单一字符串文字来初始化TEST1和TEST2。如果你被允许改变字符串字面...

test1[10] = 'x';  /* attempt to change the 's' */ 
printf("%s\n", test2); /* print "text", not "test"! */ 
+0

标准摘录中的欢呼声! – 2009-10-30 00:25:25