C 字符串操作指针与数组表示法



为什么第一个版本会使程序崩溃,而第二个版本不会?它们不是一回事吗?

指针表示法

char *shift = "mondo";
shift[3] = shift[2];

数组表示法

char shift[] = {'m', 'o', 'n', 'd', 'o', ''};
shift[3] = shift[2];

兆威

int main( void )
{
    char *shift = "mondo";
    shift[3] = shift[2];
    char shift[] = {'m', 'o', 'n', 'd', 'o', ''};
    shift[3] = shift[2];
    return 0;
}

不!这是 C 语言中的重要问题之一。首先,你创建一个指向内存只读部分的指针,即你不能改变它,只能读取它。第二个,创建一个字符数组,即连续字符的内存的一部分,您可以在其中具有读取和写入访问权限,这意味着您可以读取和更改数组的值。

第一个指向字符串文字(通常在代码的只读部分中,应该确实const char *但由于历史原因能够侥幸逃脱)|。

第二个创建一个数组,然后填充该数组。

因此它们不一样

第一个是在 中分配内存。文本段,而第二个将其放入 .BSS。 内存在 .文本段实际上是只读的或const

 char *string = "AAAA";

这将创建有效的const char *,因为内存将在 .文本段作为字符串文本。 由于这通常会标记为只读,因此尝试写入它将生成访问冲突或分段错误。

您要执行此操作:

 char string[] = "AAAA";

这将按预期工作,并为四个大写的 As 字符串分配内存,并使用变量 string 作为指向该位置的指针。

这将创建一个指向现有字符串的指针:

char *shift = "mondo";

这将创建一个新的字符数组:

char shift[] = {'m', 'o', 'n', 'd', 'o', ''};

在第二种情况下,您可以修改字符,因为它们是您刚刚创建的字符。

在第一种情况下,您只是指向一个永远不应修改的现有字符串。 字符串存储位置的详细信息取决于特定的编译器。 例如,它可以将字符串存储在不可修改的内存中。 编译器还可以执行一些技巧以节省空间。 例如:

 char *s1 = "hello there";
 char *s2 = "there";

s2实际上可能指向位于s1指向的字符串第七个位置的同一字母"t"。

为避免混淆,最好将 const 指针与字符串文字一起使用:

const char *shift = "mondo";

这样,编译器会在您不小心尝试修改它时通知您。

每当使用 char * str = "hello";这是编译器隐式表达的 const char * str= "hello";这使得此符号转到程序存储器的只读位置。

但在数组的情况下,相同的解释为 char const *array[]; 这就是为什么当用户尝试更改数组的基址时编译器会尖叫的原因。这是编译器隐式完成

最新更新