为什么C中的文本字符串赋值对于指定长度的数组是不可能的?

Why is literal string assignment in C not possible for array with specified length?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
What is the difference between char s[] and char *s in C?
Do these statements about pointers have the same effect?

一直以来,我都认为每当我需要复制一个字符串(无论是文字还是变量)时,我都需要使用strcpy()。然而,我最近发现:

1
char a[]="test";

而这

1
char *a="test";

据我所知,第二种类型是不安全的,在某些情况下会打印垃圾。对吗?更让我好奇的是,为什么以下内容不起作用:

1
2
char a[5];
a="test";

或者这个

1
2
char a[];
a="test";

但这是可行的

1
2
char *a;
a="test";

如果有人能把事情弄清楚一点,我会很高兴的。


char a[]="test";

它声明并初始化一个大小为5的数组,其中包含"test"的内容。

char *a="test";

这声明并初始化指向文字"test"的指针。试图通过a修改文字是未定义的行为(可能会导致您看到的垃圾)。它不是不安全的,只是不能修改,因为文字是不可变的。

char a[5];
a="test";

即使当a"test"具有完全相同的类型时,这也失败了,就像任何其他试图通过赋值复制数组的尝试一样。

char a[];
a="test";

这将声明一个大小未知的数组。申报书在使用前应填写完整。

char *a;
a="test";

这很好,因为"test"衰减到指向文字第一个元素的指针。尝试修改其内容仍然是未定义的行为。


让我们逐个分析:

1
char a[]="test";

这就告诉编译器在堆栈上分配5个字节,将't''e''s''t''\0'放在堆栈上。然后,变量a指向写入't'的位置,您有一个指针指向具有5个可用空间的有效位置。(也就是说,如果您将a视为指针。事实上,编译器仍然将a视为单个自定义类型,由5个char组成。在极端情况下,您可以想象它类似于struct { char a, b, c, d, e; } a;

1
char *a="test";

"test"(如我所说,基本上是't''e''s''t''\0'存储在程序中的某个地方,比如"literal's area",a指向它。该区域不是您可以修改的,而是您可以阅读的。a本身没有任何特定的内存(我不是说指针值的4/8字节)。

1
2
char a[5];
a ="test";

您要告诉编译器将一个字符串的内容复制到另一个字符串。这不是一个简单的操作。对于char a[] ="test";,这相当简单,因为堆栈上只有5个push。然而,在这种情况下,它是一个需要1乘1复制的循环。

定义char a[];,我认为这是不可能的,是吗?您要求a是一个数组,其大小将在初始化时确定。当没有初始化的时候,就没有意义了。

1
2
char *a;
a ="test";

您将a定义为指向char数组的指针。当你把它分配给"test"时,a只是指向它,但它没有任何特定的内存,就像char *a ="test";的情况一样。

如我所说,分配数组(无论是以空结尾的char(string)数组还是任何其他数组)是编译器不为您做的一项重要任务,这就是为什么您要为它提供函数的原因。


不要混淆C中的赋值和初始化,它们是不同的。

在C语言中,字符串不是数据类型,它是一种约定,使用数组和nul终止符。与任何数组一样,当您分配它时,它的名称解析为一个指针。可以指定指针,但这与指定字符串不同。