2009-09-10 110 views
3

我的代碼段錯誤,我不知道爲什麼。寫入c字符串

1 #include <stdio.h> 
2 
3 void overwrite(char str[], char x) { 
4 int i; 
5 for (i = 0; str[i] != '\0'; i++) 
6  str[i] = x; 
7 } 
8 
9 int main(void) { 
10 char *s = "abcde"; 
11 char x = 'X'; 
12 overwrite(s, x); 
13 printf("%s\n", s); 
14 return 0; 
15 } 

gdb調試器告訴我,這個問題是在第6行,在這裏我要存儲一個char,爲C-字符串(如果我用左值指針引用,這是同樣的問題。)這是什麼他說:

(gdb) run 
Starting program: /tmp/x/x 

Breakpoint 1, overwrite (str=0x8048500 "abcde", x=88 'X') at x.c:5 
5   for (i = 0; str[i] != '\0'; i++) 
(gdb) s 
6   str[i] = x; 
(gdb) 

Program received signal SIGSEGV, Segmentation fault. 
0x080483e3 in overwrite (str=0x8048500 "abcde", x=88 'X') at x.c:6 
6   str[i] = x; 
(gdb) q 

我給K & RC本書的學習,這從章節2.8(刪除功能)簡化的例子。我不知道問題在哪裏。

回答

17

因爲char * s =「abcde」;在只讀內存中創建字符串。嘗試

char s[] = "abcde"; 

編輯:解釋:char *是指針,「abcde」在只讀內存中創建 - >不可變。

炭[]是數組,其被完全存儲在棧和從存儲器初始化,因此是可變的

-2

我的猜測是在其中定義類型作爲字符數組的參數定義。當你在一個指針傳遞給一個char

你可以嘗試改變第一行是:

void overwrite(char *str, char x) { 

字符數組和字符指針是語義不相同。

+0

'炭STR []'和'字符* str'是等價作爲函數參數。 – sepp2k 2009-09-10 14:34:16

+0

你錯了,在參數列表中使用時,char str []會衰減到char *'。 – avakar 2009-09-10 14:35:33

+0

好的....但我是對的,他們在某些情況下是不同的權利?你能否詳細說明在不同的情況下? – Toad 2009-09-10 14:36:23

2

當您定義一個指向字符串字符的指針時,將其聲明爲const char *

const char *s = "abcde"; 

這樣,當您嘗試將該字符串發送到overwrite()函數時,編譯器會發出抱怨。

const char *s = "abcde"; 
char t[] = "fghij"; 
char x = 'X'; 

overwrite(s, x); /* oops */ 
overwrite(t, x); /* ok */ 
1

並不意見,但只是爲了闡述:考慮如果編譯器允許這樣做會發生什麼。你可以寫:

char *s1="abcde"; 
char *s2="abcde"; 
s1[0]='x'; 
puts(s1); 
puts(s2); 

如果編譯器識別出兩個字符串是相同的,並重新使用它們,但後來也允許線3條,你的輸出將是:

xbcde 
xbcde 

這很有可能不是你想要的。如果這兩個文字在程序的廣泛分離部分,這將是特別神祕的。

+0

這就是爲什麼.Net字符串是不可變的。它*通過稱爲「字符串實習」的東西來重用字符串。 – 2009-09-10 15:20:36

+0

@Tom Ritter - 是的,這就是爲什麼.Net是一個完全不同的平臺,其目標完全不同於C。 – 2009-09-11 05:14:18

-1

試試:

#include <iostream> 
#include <cstring> 

using namespace std; 

void overwrite(char[], char); 

int main(void) 
{ 
     char *s = strdup("abcde"); 
     char X = 'X'; 
     overwrite(s, X); 
     cout << s << endl; 

     if(s!=NULL) 
       delete [] s; 

     return 0; 
} 

void overwrite(char str[], char x) 
{ 
     for(int i=0; str[i]!='\0'; i++) 
       str[i] = x; 
} 
+0

問題被標記爲C ...並且如果您要檢查s爲NULL,您可以在strdup()調用,而不是使用無效指針。 – pmg 2009-09-10 16:36:02

+0

也strdup做一個malloc()...調用delete []是錯誤的。 – Nicholaz 2009-11-17 14:37:30