2010-11-03 26 views
8

Olası Yinelenen:strtok - char işaretçi karşı karakter dizisi


strtok wont accept: char *str

parçalama arızası bir char * yerine char [] bir sonuçları kullanılarak, strtok işlev.

Bu düzgün çalışır:

char *string = "hello world"; 
char *result = strtok(string, " "); 

kimse davranışındaki bu fark neden açıklayabilir:

char string[] = "hello world"; 
char *result = strtok(string, " "); 

Bu bir segment hataya neden olur? İkinci örnekte

cevap

23
char string[] = "hello world"; 

Bu hat (bu durumda char[12] olarak) karakterlerin büyük yeterince dizisi olmaya string başlatır. Yerel diziye kopyalar bu karakterleri Eğer

char string[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\0' }; 

diğer çizgi dışarı yazmıştı sanki:

char* string = "hello world"; 

Bunun sadece yerel işaretçi başlatır, yerel bir diziyi başlatmak değil. derleyici kodu nedeni C alçıda olmadan bu izin verir

const char literal_string[] = "hello world"; 
char* string = (char*) literal_string; 

olduğu gibi olsa, sen değiştirmek izin yok bir diziye bir işaretçi olarak ayarlayın izin antik kod izin esas olan derlemeye devam et. Kaynak kodunuzdaki bir dizgi değişkeni türünün olduğunu, const char*'a dönüştürebileceğini, ancak hiçbir zaman bir char*'a dönüştürmeyeceğini varsaymalısınız.

+0

Pek çok iyi cevap, ancak bunu temel sorunun en net örneğini buldum. –

+0

+1 mükemmel bir açıklama –

10

:

char *string = "hello world"; 
char *result = strtok(string, " "); 

string değiştirilemez bir dizgi, işaret işaretçi (strtok() olarak yapmak gibi olacaktır).

char *string = strdup("hello world"); 
char *result = strtok(string, " "); 

böylece string edebi bir değiştirilebilir kopyasına işaret:

Sen çizgisinde bir şey yapabiliriz.

+0

Ben dürtüye -1 karşı direneceğim, ama gerçekten bu cevabı sevmiyorum. Sanırım yeni başlayan kodlayıcıları, belleğin nasıl yönetileceğini (ve özellikle dizeleri) öğrenmekten ziyade segfaults'ları çözmek için “strdup” a atıyor. Ama daha iyi bir cevabın "diziyi kullanmanız veya dizginiz için dinamik olarak bellek ayırmanız" gerekmediği konusunda emin değilim. Bu arada, strdup' standart C değil, ama tabii ki bu sistemde olmayan sistemlerde uygulanması kolay. –

0

ilk vaka dize tutacak kadar büyük ve dizesinin içeriğiyle ile başlatır bir (non const) karakter dizisi oluşturur. İkinci durumda bir char işaretçisini oluşturur ve büyük ihtimalle salt okunur bellekte saklanan dize değişmezini işaret edecek şekilde başlatır. strtok hafızayı değiştirmek istiyor beri

bunu geçmesi argüman tarafından, ikincisi durum tanımsız davranış onun unsuprising böylece, (bir (const de işaret eden bir pointer) dize içinde geçiyoruz) neden göstererek öyle ikinci durumda (char *) olarak

3

çöküyor, dize salt okunur bellekte olduğunu. doğru dize sabitleri const char * şeklindedir ve değişkeni bildirmek için bu türünü kullanırsanız, değiştirmeyi denediğinizde derleyici tarafından uyarılırsınız. Tarihsel nedenlerle, değiştirilemelerine rağmen char * türündeki değişkenleri başlatmak için dize sabitleri kullanmanıza izin verilir. (Bazı derleyiciler gcc en -Wwrite-strings ile örneğin, kapalı bu tarihi lisansı dönelim.)

+0

Ayrıca, ilk durumda, dizgenin literalinin gizli dizisine char dizisine kopyalanmasından da bahsetmek gerekir. Bu yüzden aynı konuya sahip değilsiniz. –

+0

'const char *' aslında strtok ile kullanılmaya çalışılırsa bir segfault ile sonuçlanır, ancak en azından bir derleme uyarısı verir. Ancak konu olan değişiklik hakkında dikkat çekti. –

+0

Evet, daha az telgraf olmalıydım. Cevap düzenlendi. – zwol

0

ikincisi sabit dize bir işaretçi (yani değiştirebilir) beyan Çünkü ...

Yani derleyici bağlı/platform/OS/bellek haritası ... "merhaba dünya" dizgesi sabit olarak (gömülü bir sistemde, ROM'da saklanabilir) saklanacak ve bu hatayı değiştirmeye çalışacaktır.

4

strtok kendisine iletmek dize değiştirir (ya neyse çalışır). İlk kodunuzda, belirli bir değere başlatılan bir dizinin adresini iletiyorsunuz - ancak normal bir char dizisi olduğundan, değiştirilmesine izin verilir. İkinci kodunda

, sen, bir dizgi adresini geçiyoruz.Bir dizgi değişmezini değiştirmeye çalışmak tanımsız davranış verir.