strtok – char数组与char指针

可能重复:
strtok不接受:char * str

使用strtok函数时,使用char *而不是char []导致分段错误。

这运行正常:

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

这会导致分段错误:

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

任何人都能解释导致这种行为差异的原因吗?

 char string[] = "hello world"; 

此行将string初始化为足够大的字符数组(在本例中为char[12] )。 它将这些字符复制到您的本地数组中,就像您已经写出来一样

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

另一行:

 char* string = "hello world"; 

不初始化本地数组,它只是初始化一个本地指针。 允许编译器将其设置为指向您不允许更改的数组的指针,就像代码一样

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

C允许这个没有演员的原因主要是让古代代码继续编译。 您应该假装源代码中字符串文字的类型是const char[] ,它可以转换为const char* ,但绝不会将其转换为char*

在第二个例子中:

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

指针string指向一个字符串文字,无法修改(如strtok()希望的那样)。

你可以做一些事情:

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

以便string指向文字的可修改副本。

strtok修改你传递给它的字符串(或尝试无论如何)。 在第一个代码中,您将已初始化的数组的地址传递给特定值 – 但由于它是一个正常的char数组,因此允许修改它。

在第二个代码中,您传递的是字符串文字的地址。 尝试修改字符串文字会产生未定义的行为。

在第二种情况( char * )中,字符串位于只读存储器中。 正确类型的字符串常量是const char * ,如果您使用该类型来声明变量,那么当您尝试修改它时,编译器会收到警告。 由于历史原因,您可以使用字符串常量初始化char *类型的变量,即使它们无法修改。 (有些编译器允许您关闭此历史许可证,例如使用gcc的-Wwrite-strings 。)

第一种情况创建一个(非常量)char数组,该数组足以容纳字符串并使用字符串的内容对其进行初始化。 第二种情况创建一个char指针并将其初始化为指向字符串文字,该文字可能存储在只读存储器中。

由于strtok想要修改你传递它的参数所指向的内存,后一种情况会导致未定义的行为(你传入一个指向(const)字符串文字的指针),所以它崩溃了它崩溃了

因为第二个声明一个指针(可以改变)到一个常量字符串……

因此,根据您的编译器/平台/ OS /内存映射…“hello world”字符串将存储为常量(在嵌入式系统中,它可能存储在ROM中)并尝试修改它将导致该错误。