C中的字符串:为什么这有效?

时间:2013-03-28 02:18:02

标签: c

我很抱歉,因为它显然没有被破坏,但我的(新手)对C处理字符串文字的方式的理解告诉我这不应该有效......

char some_array_of_strings[3][200];
strcpy(some_array_of_strings[2], "Some garbage");
strcpy(some_array_of_strings[2], "Some other garbage");

我认为C阻止了字符串文字的直接修改,这就是处理字符串时使用指针的原因。这个作品的事实告诉我,我误解了一些东西。

此外,如果这有效,为什么......

some_array_of_strings[1]="Some garbage"
some_array_of_strings[1]="Some garbage that causes a compiler error due to reassignment"

不起作用?

5 个答案:

答案 0 :(得分:4)

注意短语“字符串数组”。 “字符串”不是C中的数据类型;它是一个数据布局。具体而言,字符串定义为

  

由(包括)终止并包括的连续字符序列   第一个空字符

char的数组可能包含字符串,而char*指针可能指向(字符串的第一个字符)。 (该标准将指向字符串第一个字符的指针定义为指向字符串的指针。)

char some_array_of_strings[3][200];

这定义了一个3元素数组,其中每个元素都是char的200个元素数组。 (它是一个二维数组,在C中只是一个数组数组。)

strcpy(some_array_of_strings[2], "Some garbage");

字符串文字"Some garbage"引用匿名静态分配的char数组;它存在于程序的整个执行过程中,并且不允许您对其进行修改。 strcpy()调用,顾名思义,的数据的内容(包括终止'\0' null字符)复制到some_array_of_strings[]

strcpy(some_array_of_strings[2], "Some other garbage");

同样的事情:这会将内容"Some other garbage"复制到some_array_of_strings[2],覆盖您在上一行复制的内容。在这两种情况下,都有足够的空间。

你没有修改字符串文字,你是通过从字符串文字复制字节来修改你自己的数组(更确切地说,从我上面提到的那个匿名数组)。

some_array_of_strings[1]="Some garbage";

这不只是“不行”,这是非法的。 C中没有数组赋值。

让我们举一个更简单的例子:

char arr[10];
arr = "hello"; /* also illegal */

arr是数组类型的对象。在大多数上下文中,数组类型的表达式被隐式转换为指向数组对象的第一个元素的指针。这适用于作业的两面:对象名称arr和字符串文字"hello"

但是左侧的指针只是指针。没有指针对象。在技​​术方面,它不是左值,因此它不能出现在作业的左侧,只能写出42 = x;}。

(如果没有发生数组到指针的转换,它仍然是非法的,因为C不允许数组赋值。)

有关赋值左侧数组问题的更多详细信息:

数组表达式衰变为指针的上下文是数组表达式为:

  • 一元sizeof运算符的操作数;
  • 一元&(地址)运算符的操作数;或
  • 初始化程序中用于初始化数组对象的字符串文字。

作业的左侧不是任何上下文,所以在:

char array[10];
array = "hello";

LHS原则上被转换为指针。但是结果指针表达式不再是左值,这使得赋值变为约束违规。

查看它的一种方法是将表达式array转换为指针,然后使赋值非法。另一个是因为赋值是非法的,所以整个程序都不是有效的C,所以它没有定义的行为,并且询问是否发生任何转换是没有意义的。

(我使用“非法”这个词玩得有点松散,但这个答案已经足够长,所以我不会进入它。)

推荐阅读:comp.lang.c FAQ的第6节;它很好地解释了C中数组和指针之间经常令人困惑的关系。

答案 1 :(得分:3)

您没有修改字符串文字,而是将其用作将其复制到字符数组中的源。复制完成后,您的字符串文字与数组中的副本无关。然后您可以自由操纵数组。

答案 2 :(得分:1)

根据您的定义,char some_array_of_strings[3][200];表示some_array_of_strings是3个元素的array个,每个元素本身是一个200个字符的array或长度为{{1}的字符串200 1}}字符。

strcpy(some_array_of_strings[2], "Some garbage");
strcpy(some_array_of_strings[2], "Some other garbage");

在这两个声明中,您实际上char pointer复制到有效的另一个char pointersome_array_of_strings[2]实际上类似于char[200],类似于char *

some_array_of_strings[1]="Some garbage";
some_array_of_strings[1]="Some garbage that causes a compiler error due to reassignment";

在这里,您char * "Some garbage" char[200]分配给some_array_of_strings[1] assigning,即不支持copying。区别在于{{1}}和{{1}}内容。

答案 3 :(得分:1)

some_array_of_strings[1]="Some garbage"
some_array_of_strings[1]="Some garbage that causes a compiler error due to reassignment"

在第一行中,将some_array_of_strings [1]分配给字符串文字,以便some_array_of_strings [1]或& some_array_of_strings [1]的地址指向字符串文字。因此,在第二行中,当您尝试重新分配some_array_of_strings [1]时,它会给您错误。

正如Keith和Fred所说的那样,strcpy你只是将字符串文字的字符复制到你的数组中。

答案 4 :(得分:1)

some_array_of_strings[2]是一个包含200个字符的数组。

当它在大多数表达式中使用时,它会“衰变”(转换的花哨词)成为指向数组第一个元素的指针。

strcpy(some_array_of_strings[2], "Some garbage");然后将"Some garbage"逐个字符复制到200个字符的数组中,方法是使用指向数组第一个元素的指针并逐个推进。

在大多数表达式中,"Some garbage"是指向包含相应字符和字符串终止字符('\0')的字符数组的指针。

另一方面,

some_array_of_strings[1]="Some garbage"尝试将指针(指向字符串)分配给指向200个字符的第一个元素的常量/不可修改指针,这也是非法的(如执行1=2;