我知道 C 中的数组只是指向顺序存储数据的指针。但是什么不同意味着符号[]和*的不同。我的意思是在所有可能的使用环境中。例如:
char c[] = "test";
如果您在函数体中提供此指令,它将在堆栈上分配字符串,而
char* c = "test";
将指向一个数据(只读)段。
您能否在所有使用上下文中列出这两种符号之间的所有差异,以形成清晰的总体视图。
根据C99标准:
数组类型描述了一组连续分配的具有特定成员对象类型(称为元素类型)的非空对象。
- 数组类型的特征在于它们的元素类型和数组中元素的数量。数组类型被称为从其元素类型派生,如果其元素类型是
T
,则该数组类型有时称为数组T
。从元素类型构造数组类型称为数组类型派生。
指针类型可以派生自函数类型、对象类型或不完整类型,称为引用类型。指针类型描述了一个对象,其值提供对被引用类型实体的引用。从引用类型派生的指针类型
T
有时称为指向 的指针T
。从引用类型构造指针类型称为指针类型派生。
根据标准声明……</p>
char s[] = "abc", t[3] = "abc";
char s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };
……是相同的。数组的内容是可修改的。另一方面,声明……</p>
const char *p = "abc";
...将 p 的类型定义为指向常量char
的指针,并将其初始化为指向类型为常量数组char
(在 C++ 中)的对象,其长度为 4,其元素使用字符串字面量进行初始化。如果尝试使用p
来修改数组的内容,则行为未定义。
根据6.3.2.1数组下标取消引用和数组下标是相同的:
下标运算符的定义
[]
与E1[E2]
相同(*((E1)+(E2)))
。
数组与指针的区别在于:
有关该主题的更多有用信息,请访问 http://www.cplusplus.com/forum/articles/9/
char c[] = "test";
这将创建一个包含字符串 test 的数组,以便您可以修改/更改任何字符,例如
c[2] = 'p';
但,
char * c = "test"
它是一个字符串文字——它是一个 const char。
因此,对这个字符串文字进行任何修改都会给我们带来段错误。所以
c[2] = 'p';
现在是非法的并给我们段错误。
char []
表示类型“char 的未知边界数组”,而char *
表示类型“指向 char 的指针”。正如您所观察到的,当使用字符串文字初始化“char 的未知边界数组”类型的变量的定义时,该类型将转换为“char 的数组 [N]”,其中 N 是适当的大小。这同样适用于从数组聚合初始化:
int arr[] = { 0, 1, 2 };
arr 被转换为“array[3] of int”类型。
在用户定义的类型定义 ( struct
,class
或union
) 中,C++ 中禁止未知绑定数组类型,尽管在某些 C 版本中它们被允许作为结构的最后一个成员,在那里它们可用于访问已分配的结构结束后的内存;这种用法称为“灵活数组”。
递归类型构造是另一个区别。可以构造指向char *
(例如char **
,char (*)[10]
)的指针和数组,但这对于未知边界的数组是非法的;一个人不能写或char []*
(char [][10]
虽然很好)。char (*)[]
char [10][]
最后,cv-qualification 的操作方式不同;给定typedef char *ptr_to_char
和typedef char array_of_unknown_bound_of_char[]
,指针版本的 cv 限定将按预期运行,而数组版本的 cv 限定会将 cv 限定迁移到元素类型:也就是说,const array_of_unknown_bound_of_char
等效于const char []
而不是虚构的char (const) []
. 这意味着在函数定义中,数组到指针的衰减在构造原型之前对参数进行操作,
void foo (int const a[]) {
a = 0;
}
是合法的;无法使未知绑定数组参数不可修改。
如果您知道声明指针变量不会创建变量的类型,那么整个事情就会变得清晰,它指向。它创建一个指针变量。
因此,在实践中,如果您需要一个字符串,那么您需要指定一个字符数组,并且稍后可以使用一个指针。
实际上数组等价于常量指针。
此外, char c[] 为数组分配内存,其基址是 c 本身。没有分配单独的内存来存储该地址。
写入 char *c 会为其基地址存储在 c 中的字符串分配内存。此外,一个单独的内存位置用于存储 c。