gpt4 book ai didi

c++ - 数组是指针吗?

转载 作者:IT老高 更新时间:2023-10-28 22:15:33 25 4
gpt4 key购买 nike

数组和指针在 C 和 C++ 中的实现方式不同吗?我遇到了这个问题,因为在这两种情况下,我们都从元素的起始地址访问元素。所以,它们之间应该有密切的关系。请解释它们之间的确切关系。谢谢。

最佳答案

让我们先把重要的东西弄清楚:数组不是指针。数组类型和指针类型是完全不同的东西,编译器的处理方式也不同。

产生混淆的地方在于 C 如何处理数组表达式N1570 :

6.3.2.1 Lvalues, arrays, and function designators

...
3 Except when it is the operand of the sizeof operator, the _Alignof operator, or theunary & operator, or is a string literal used to initialize an array, an expression that hastype ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that pointsto the initial element of the array object and is not an lvalue. If the array object hasregister storage class, the behavior is undefined.

让我们看看下面的声明:

int arr[10] = {0,1,2,3,4,5,6,7,8,9};
int *parr = arr;

arrint 的 10 元素数组;它指的是一 block 足够大的连续内存块,可以存储 10 个 int 值。第二个声明中的表达式 arr 是数组类型,但由于它不是&sizeof 的操作数> 并且不是字符串字面量,表达式的类型变成“指向int的指针”,值为第一个元素的地址,或者&arr[0]

parr 是一个指向 int 的指针;它指的是一 block 大到足以容纳单个 int 对象的地址的内存块。如上所述,它被初始化为指向 arr 中的第一个元素。

这是一个假设的内存映射,显示了两者之间的关系(假设 16 位整数和 32 位地址):

Object           Address         0x00  0x01  0x02  0x03------           -------         ----------------------   arr           0x10008000      0x00  0x00  0x00  0x01                 0x10008004      0x00  0x02  0x00  0x03                 0x10008008      0x00  0x04  0x00  0x05                 0x1000800c      0x00  0x06  0x00  0x07                 0x10008010      0x00  0x08  0x00  0x09  parr           0x10008014      0x10  0x00  0x80  0x00

The types matter for things like sizeof and &; sizeof arr == 10 * sizeof (int), which in this case is 20, whereas sizeof parr == sizeof (int *), which in this case is 4. Similarly, the type of the expression &arr is int (*)[10], or a pointer to a 10-element array of int, whereas the type of &parr is int **, or pointer to pointer to int.

Note that the expressions arr and &arr will yield the same value (the address of the first element in arr), but the types of the expressions are different (int * and int (*)[10], respectively). This makes a difference when using pointer arithmetic. For example, given:

int arr[10] = {0,1,2,3,4,5,6,7,8,9};
int *p = arr;
int (*ap)[10] = &arr;

printf("before: arr = %p, p = %p, ap = %p\n", (void *) arr, (void *) p, (void *) ap);
p++;
ap++;
printf("after: arr = %p, p = %p, ap = %p\n", (void *) arr, (void *) p, (void *) ap);

“之前”行应该为所有三个表达式打印相同的值(在我们的假设映射中,0x10008000)。 “after”行应该显示三个不同的值:0x100080000x10008002(base plus sizeof (int))和0x10008014(基数加 sizeof (int [10]))。

现在让我们回到上面的第二段:数组表达式在大多数情况下都被转换为指针类型。让我们看一下下标表达式arr[i]。由于表达式 arr 不是作为 sizeof& 的操作数出现,并且因为它不是用于初始化另一个的字符串文字数组,它的类型从“int的10元素数组”转换为“指向int的指针”,并且正在对这个指针<进行下标操作/em> 值。事实上,当您查看 C 语言定义时,您会看到以下语言:

6.5.2.1 Array subscripting
...
2 A postfix expression followed by an expression in square brackets [] is a subscripted designation of an element of an array object. The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2))). Because of the conversion rules that apply to the binary + operator, if E1 is an array object (equivalently, a pointer to the initial element of an array object) and E2 is an integer, E1[E2] designates the E2-th element of E1 (counting from zero).

实际上,这意味着您可以将下标运算符应用于指针对象就好像它是一个数组。这就是为什么代码喜欢

int foo(int *p, size_t size)
{
int sum = 0;
int i;
for (i = 0; i < size; i++)
{
sum += p[i];
}
return sum;
}

int main(void)
{
int arr[10] = {0,1,2,3,4,5,6,7,8,9};
int result = foo(arr, sizeof arr / sizeof arr[0]);
...
}

按照它的方式工作。 main 处理的是 int 数组,而 foo 处理的是指向 int 的指针,但两者都是能够使用下标运算符就好像他们都在处理一个数组类型。

这也意味着数组下标是可交换的:假设a是一个数组表达式,i是一个整数表达式,a[ i]i[a] 都是有效的表达式,并且都会产生相同的值。

关于c++ - 数组是指针吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3959705/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com