strtok - char数组与char指针

时间:2010-11-03 18:39:09

标签: c arrays pointers strtok

  

可能重复:
  strtok wont accept: char *str

使用strtok功能时,使用char *代替char []会导致分段错误。

运行正常:

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

这会导致分段错误:

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

任何人都可以解释造成这种行为差异的原因吗?

6 个答案:

答案 0 :(得分:28)

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*

答案 1 :(得分:14)

在第二个例子中:

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

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

您可以采取以下措施:

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

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

答案 2 :(得分:4)

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

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

答案 3 :(得分:3)

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

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

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

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