char* 和 char[] 不是相同类型吗?

4

可能是重复问题:
为什么在写入字符串时会导致分段错误?

我在我的C代码中遇到了一个奇怪的问题。我正在尝试使用strtok函数来拆分字符串,但我得到了访问冲突异常。这是我的代码:

char *token;
char *line = "LINE TO BE SEPARATED";
char *search = " ";
token = strtok(line, search); <-- this code causes crash

然而,如果我将char *line改为char line[],一切都按预期工作,我不会得到任何错误。有人能解释一下为什么使用strtok时会出现这种(对我来说很奇怪的)行为吗?我以为char*和char[]是相同且完全相同的类型。
更新:我正在使用MSVC 2012编译器。

1
你的编译器应该拒绝或至少警告将类型转换为 char*(在 C++11 中不再允许)。提高警告级别。 - R. Martinho Fernandes
1
@hmjd 类型转换在C和C++中的行为并不一定相同。 - Gorpik
@Gorpik,我问的唯一原因是似乎没有C++特定的代码。如果是C++,那么有更好的方法来完成这个任务(例如使用流)。 - hmjd
@hmjd 你是对的,我修改了标签。 - Davita
4个回答

8

strtok()函数会修改其解析的字符串。如果您使用:

char* line = "...";

如果修改了字符串文字,则属于未定义行为。当您使用以下代码时:

char[] line = "...";

如果修改的是字符串字面量,则会修改其副本。


1
正确;一个快速的解决方法是编写 char *line = strdup("LINE TO BE SEPARATED"),但请务必在之后释放内存。值得注意的是,gcc 在编译时会对此发出警告。对于 MSVC,您应该启用所有警告以捕获此类错误。 - csl
1
@csl,关于VC的警告 (/W4/WX),您的建议非常明智。 - hmjd
1
@csl - 请注意,strdup 不是标准 C 或标准 C++ 的一部分。 - Pete Becker
1
对于 char* line = "...";,我更愿意说:正在修改只读(或const)字符串字面值。只是为了更清楚明白。 - sciarp
@PeteBecker 谢谢,我不知道! - csl
@sciarp: char* line = "..."虽然不是const。但声明为非常量是完全合法的。因此,“只读”应该是正确的术语。然而,谁说字符串字面值就是只读的呢?所以无论如何都没有必要提到它。 - netcoder

5

当将"LINE TO BE SEPARATED"分配给char *line时,您使line指向程序可执行文件中编写的常量字符串。您不被允许修改它。您应该将那些类型的变量声明为const char *

如果声明为char[],则您的字符串将在函数的堆栈上声明。因此,您可以修改它。


3
char *s = "any string"

指向字符串或字符数组的指针的定义。在上面的例子中,s 指向一个常量字符串。

char s[] = "any string"

这是char数组的定义。在上面的例子中,s是一个包含字符{'a','n','y',' ','s','t','r','i','n','g','\0'} 的char数组。

strtok会更改您输入的字符串内容。它将字符串中的分隔符替换为'\0'(空值)。

因此,您不能像这样使用strtok处理常量字符串:

char *s="any string"

你可以使用动态内存或静态内存来使用strtok,例如:
char *s = malloc(20 * sizeof(char)); //dynamic allocation for string
strcpy(s,"any string");


char s[20] = "any string"; //static allocation for string
char s[] = "any string"; //static allocation for string

1
回答你的问题:char* 和 char[] 不是同一种类型? 这个:
char *line = "LINE TO BE SEPARATED";

字符串字面值定义在只读内存中。您无法更改此字符串。

然而,这个:

char line[] = "LINE TO BE SEPARATED";

现在是一个字符数组(引号中的文本已复制到数组中)放置在堆栈上。您可以修改此数组中的字符。

因此,它们都是字符数组,但放置在内存的不同部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接