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

时间:2016-01-24 15:21:14

标签: c string

为什么第一个版本会导致程序崩溃,而第二个版本却没有?他们不是一回事吗?

指针符号

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

数组表示法

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

MWE

int main( void )
{
    char *shift = "mondo";
    shift[3] = shift[2];

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

    return 0;
}

5 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:3)

第一个指向字符串文字(通常在代码的只读部分,应该是const char *shift = "mondo"; 但由于历史原因能够逃脱)|。

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

因此它们不一样

答案 2 :(得分:2)

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

 char *string = "AAAA";

这会创建实际上是const char *的内容,因为内存将作为字符串文字在.TEXT段中分配。由于这通常会被标记为只读,因此尝试写入它将产生访问冲突或分段错误。

你想这样做:

 char string[] = "AAAA";

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

答案 3 :(得分:1)

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

TreeMap

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

char *shift = "mondo";

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

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

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

char *s1 = "hello there"; char *s2 = "there"; 实际上可能指向位于s2所指向的字符串的第七个位置的相同字母't'。

为避免混淆,更喜欢使用带有字符串文字的const指针:

s1

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

答案 4 :(得分:1)

每当使用时定义字符串 char * str = "hello"; 这由编译器隐式表达 const char * str= "hello"; 这使得这个符号只读取程序存储器的位置。

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

隐式完成的