C/C++ int[] 与 int*(指针与数组表示法)。有什么不同?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11555997/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:15:05  来源:igfitidea点击:

C/C++ int[] vs int* (pointers vs. array notation). What is the difference?

c++carrayspointersstandards

提问by Alexander Reshytko

I know that arrays in C are just pointers to sequentially stored data. But what differences imply the difference in notation [] and *. I mean in ALL possible usage context. For example:

我知道 C 中的数组只是指向顺序存储数据的指针。但是什么区别意味着符号 [] 和 * 的区别。我的意思是在所有可能的使用环境中。例如:

char c[] = "test";

if you provide this instruction in a function body it will allocate the string on a stack while

如果您在函数体中提供此指令,它将在堆栈上分配字符串,而

char* c = "test";

will point to a data (readonly) segment.

将指向一个数据(只读)段。

Can you list all the differences between these two notations in ALL usage contexts to form a clear general view.

您能否在所有用法上下文中列出这两种符号之间的所有差异以形成清晰的总体视图。

采纳答案by Sergey K.

According to the C99 standard:

根据C99标准:

An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type.

36) Array types are characterized by their element type and by the number of elements in the array. An array type is said to be derived from its element type, and if its element type is T, the array type is sometimes called array of T. The construction of an array type from an element type is called array type derivation.

数组类型描述了具有特定成员对象类型(称为元素类型)的连续分配的非空对象集。

36) 数组类型的特征在于它们的元素类型和数组中元素的数量。一个数组类型据说是从它的元素类型派生出来的,如果它的元素类型是T,这个数组类型有时被称为数组的T。从元素类型构造数组类型称为数组类型派生

A pointer type may be derived from a function type, an object type, or an incomplete type, called the referenced type. A pointer type describes an object whose value provides a reference to an entity of the referenced type. A pointer type derived from the referenced type Tis sometimes referred to as a pointer to T. The construction of a pointer type from a referenced type is called pointer type derivation.

指针类型可以派生自函数类型、对象类型或不完整类型,称为引用类型。指针类型描述了一个对象,其值提供对被引用类型的实体的引用。从引用类型派生的指针类型T有时称为指向 的指针T。从引用类型构造指针类型称为指针类型派生

According to the standard declarations…

根据标准声明…

char s[] = "abc", t[3] = "abc";
char s[] = { 'a', 'b', 'c', '
const char *p = "abc";
' }, t[] = { 'a', 'b', 'c' };

…are identical. The contents of the arrays are modifiable. On the other hand, the declaration…

……完全一样。数组的内容是可修改的。另一方面,声明...

char c[] = "test";

…defines p with the type as pointer to constant charand initializes it to point to an object with type constant array of char(in C++) with length 4 whose elements are initialized with a character string literal. If an attempt is made to use pto modify the contents of the array, the behavior is undefined.

...将 p 的类型定义为指向常量的指针,char并将其初始化为指向一个类型char在 C++ 中)长度为 4 的常量数组的对象,其元素用字符串字面量初始化。如果尝试使用p来修改数组的内容,则行为未定义。

According to 6.3.2.1 Array subscriptingdereferencing and array subscripting are identical:

根据6.3.2.1数组下标解引用和数组下标是相同的:

The definition of the subscript operator []is that E1[E2]is identical to (*((E1)+(E2))).

下标操作符的定义[]E1[E2]相同(*((E1)+(E2)))

The differences of arrays vs. pointers are:

数组与指针的区别在于:

  • pointer has no information of the memory size behind it (there is no portable way to get it)
  • an array of incomplete type cannot be constructed
  • a pointer type may be derived from a an incomplete type
  • a pointer can define a recursive structure (this one is the consequence of the previous two)
  • 指针后面没有关于内存大小的信息(没有可移植的方法来获取它)
  • 不能构造不完整类型的数组
  • 指针类型可能派生自不完整的类型
  • 一个指针可以定义一个递归结构(这个是前两个的结果)

These links may be useful to the subject:

这些链接可能对主题有用:

回答by neel

c[2] = 'p';

This will create an array containing the string test so you can modify/change any character, say

这将创建一个包含字符串 test 的数组,以便您可以修改/更改任何字符,例如

char * c = "test"

but,

但,

c[2] = 'p';

It is a string literal -- it's a const char.
So doing any modification to this string literal gives us segfault. So

它是一个字符串文字——它是一个常量字符。
所以对这个字符串文字做任何修改都会给我们带来段错误。所以

int arr[] = { 0, 1, 2 };

is illegal now and gives us segfault.

现在是非法的,并给了我们段错误。

回答by ecatmur

char []denotes the type "array of unknown bound of char", while char *denotes the type "pointer to char". As you've observed, when a definition of a variable of type "array of unknown bound of char" is initialised with a string literal, the type is converted to "array[N] of char" where N is the appropriate size. The same applies in general to initialisation from array aggregate:

char []表示类型“字符的未知边界数组”,而char *表示类型“指向字符的指针”。正如您所观察到的,当使用字符串文字初始化类型为“char 的未知边界的数组”的变量的定义时,该类型将转换为“array[N] of char”,其中 N 是适当的大小。这同样适用于从数组聚合初始化:

void foo (int const a[]) {
    a = 0;
}

arr is converted to type "array[3] of int".

arr 被转换为类型“array[3] of int”。

In a user-defined type definition (struct, classor union), array-of-unknown-bound types are prohibited in C++, although in some versions of C they are allowed as the lastmember of a struct, where they can be used to access allocated memory past the end of the struct; this usage is called "flexible arrays".

在用户定义的类型定义 ( struct, classor union) 中, C++ 中禁止绑定数组类型,尽管在某些版本的 C 中它们被允许作为结构的最后一个成员,在那里它们可用于访问分配的超过结构末尾的内存;这种用法称为“灵活数组”。

Recursive type construction is another difference; one can construct pointers to and arrays of char *(e.g. char **, char (*)[10]) but this is illegal for arrays of unknown bound; one cannot write char []*or char [][10](although char (*)[]and char [10][]are fine).

递归类型构造是另一个区别;可以构造指向char *(例如char **, char (*)[10]) 的指针和数组,但这对于未知边界的数组是非法的;一个不能写char []*char [][10](虽然char (*)[]char [10][]很好)。

Finally, cv-qualification operates differently; given typedef char *ptr_to_charand typedef char array_of_unknown_bound_of_char[], cv-qualifiying the pointer version will behave as expected, while cv-qualifying the array version will migrate the cv-qualification to the element type: that is, const array_of_unknown_bound_of_charis equivalent to const char []and not the fictional char (const) []. This means that in a function definition, where array-to-pointer decay operates on the arguments prior to constructing the prototype,

最后,cv-qualification 的操作方式不同;给定typedef char *ptr_to_charand typedef char array_of_unknown_bound_of_char[], cv 限定指针版本将按预期运行,而 cv 限定数组版本会将 cv 限定迁移到元素类型:也就是说,const array_of_unknown_bound_of_char相当于const char []而不是虚构的char (const) []。这意味着在函数定义中,数组到指针衰减在构造原型之前对参数进行操作,

##代码##

is legal; there is no way to make the array-of-unknown-bound parameter non-modifiable.

是合法的;没有办法使数组的未知绑定参数不可修改。

回答by Shash

The whole lot becomes clear if you know that declaring a pointer variable does not create the type of variable, it points at. It creates a pointer variable.

如果您知道声明一个指针变量并不会创建它指向的变量类型,那么整个事情就变得很清楚了。它创建一个指针变量。

So, in practice, if you need a string then you need to specify an array of characters and a pointer can be used later on.

因此,在实践中,如果您需要一个字符串,那么您需要指定一个字符数组,并且稍后可以使用一个指针。

回答by Cygnus

Actually arrays are equivalent to constant pointers.

实际上数组等价于常量指针

Also, char c[] allocates memory for the array, whose base address is c itself. No separate memory is allocated for storing that address.

此外,char c[] 为数组分配内存,其基地址是 c 本身。没有分配单独的内存来存储该地址。

Writing char *c allocates memory for the string whose base address is stored in c. Also, a separate memory location is used to store c.

写入 char *c 会为其基地址存储在 c 中的字符串分配内存。此外,单独的内存位置用于存储 c。