C语言中的字符串字面量

6
为什么以下代码是非法的?
typedef struct{
   char a[6];
} point;

int main()
{
   point p;
   p.a = "onetwo";
}

这是否与文字大小有关?还是只是在声明char数组之后将字符串文字赋值给它是非法的?


不完全是一个重复的问题,因为这是一个包含字符数组的结构体,与普通的字符数组略有不同,我在我的回答中解释了这一点。 - dreamlax
6个回答

13

这与大小无关。在创建后,您不能将字符串字面值分配给char数组 - 只能在定义时使用它。

当您执行以下操作时:

char a[] = "something";

它创建了一个足够大小的数组(包括终止空字符),并将字符串复制到该数组中。在使用字符串字面值初始化数组时指定数组大小不是一个好习惯 - 可能没有考虑到空字符。

当你这样做时

char a[10];
a = "something";

你试图对数组的地址进行赋值,这是不合法的。

编辑:如其他答案中所提到的,你可以使用strcpy/strncpy,但一定要确保数组已经初始化为所需的长度。

strcpy(p.a, "12345");//give space for the \0

7

在数组创建后,您永远无法对其进行赋值;以下方式同样是不合法的:

int foo[4];
int bar[4];
foo = bar;

你需要使用指针或分配给数组的索引;这是合法的:
p.a[0] = 'o';

如果你想在结构体中留下一个数组,你可以使用像 strcpy 这样的函数:

strncpy(p.a, "onetwo", 6);
(注意字符数组需要足够大以容纳空终止符,因此您可能希望将其设为char a[7]并将最后一个参数更改为strncpy为7)

1
我想我应该感到受宠若惊,因为每个在我的strcpy解决方案中编辑的答案。 - Michael Mrozek
这里,给你一个+1。如果可以的话我会给你+2的,但是我发现还没有人注意到这是一个包含数组的结构体,而不仅仅是一个普通的数组。 - dreamlax
当然,与大多数其他“n”函数不同,“strncpy”自带其自身的问题。 - David Thornley

7

数组是不可修改的左值(non modifiable lvalues),因此您无法对其进行赋值。赋值运算符的左侧必须是可修改的左值(modifiable lvalue)。

但是,您可以在定义数组时对其进行初始化。

例如:

 char a[] = "Hello World" ;// this is legal
 char a[]={'H','e','l','l','o',' ','W','o','r','l','d','\0'};//this is also legal

 //but

 char a[20];
 a = "Hello World" ;// is illegal 

然而,您可以使用strncpy(a, "Hello World",20);


2
当数组被“定义”(而不是“声明”)时,如果您使用正确的术语“初始化”而不是“分配”,那么会更清晰明了。 - Jonathan Leffler

3

正如其他答案已经指出的那样,您只能使用字符串文字初始化字符数组,不能将字符串文字分配给字符数组。但是,结构体(即使包含字符数组)是另一回事。

我不建议在实际程序中这样做,但这证明了虽然数组类型不能被赋值,但包含数组类型的结构体可以。

typedef struct
{
    char value[100];
} string;

int main()
{
    string a = {"hello"};
    a = (string){"another string!"}; // overwrite value with a new string
    puts(a.value);

    string b = {"a NEW string"};
    b = a; // override with the value of another "string" struct
    puts(b.value); // prints "another string!" again
}

所以,在你的原始示例中,以下代码应该可以编译成功:
typedef struct{
    char a[6];
} point;

int main()
{
   point p;

   // note that only 5 characters + 1 for '\0' will fit in a char[6] array.
   p = (point){"onetw"};
}

对于 struct 的示例给予加分,但请注意这些复合字面量是 C99 的新增功能。('//' 样式的注释也是如此。) - schot

1

不需要使用strcpy或C99复合字面量。这是一个纯ANSI C的示例:

typedef struct{
   char a[6];
} point;

int main()
{
   point p;
   *(point*)p.a = *(point*)"onetwo";
   fwrite(p.a,6,1,stdout);fflush(stdout);
   return 0;
}

1
请注意,为了将字符串“onetwo”存储在您的数组中,它的长度必须为[7],而不是问题中所写的。额外的字符用于存储'\0'终止符。

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