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