2

我很抱歉问了一些可能看起来有点空洞的问题,因为它显然没有被破坏,但我(新手)对 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"

不行?

4

5 回答 5

4

小心“字符串数组”这个短语。“字符串”不是 C 中的数据类型;这是一个数据布局。具体来说,一个字符串被定义为

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

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

char some_array_of_strings[3][200];

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

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

字符串字面"Some garbage"量是指匿名静态分配的数组char;它存在于你的程序的整个执行过程中,你不能修改它。strcpy()顾名思义,该调用将该数组的内容复制'\0'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 中数组和指针之间经常令人困惑的关系。

于 2013-03-28T02:38:38.940 回答
3

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

于 2013-03-28T02:23:00.440 回答
1

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

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

在这两个语句中,您实际上是将内容从一个复制char pointer到另一个char pointer,这是有效的。some_array_of_strings[2]实际上是类似于char[200]which is similar to char *

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

在这里,您正在为不受支持的ie分配一个赞。区别在于和内容。char *"Some garbage"char[200]some_array_of_strings[1]assigningcopying

于 2013-03-28T02:29:09.827 回答
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 您只需将字符串文字的字符复制到数组中。

于 2013-03-28T02:29:56.013 回答
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 个字符的第一个元素的常量/不可修改指针,这也是非法的(例如 do 1=2;

于 2013-03-28T02:36:16.923 回答