【问题标题】:Array and pointers in c++ [duplicate]C ++中的数组和指针[重复]
【发布时间】:2023-03-31 23:00:03
【问题描述】:

我经常听说数组的名字是指向一块内存的常量指针,因此像这样的语句

int a[10];

int * const p= a;

在某种意义上必须相等,因为 p 是指向与数组 a[] 相同的内存块的指针,并且不能更改为指向内存中的另一个位置。

但是,如果您尝试打印这两个指针的 sizeof,您会得到不同的结果:

cout<< sizeof(a); // outputs size of 10 integer elements

虽然

cout<< sizeof(p); // outputs sizeof pointer to int

那么,为什么编译器会以不同的方式处理这两者?从编译器的角度来看,数组和指针之间的真正关系是什么?

【问题讨论】:

  • 你经常被误导——或者你只是被误解了。数组不是指针。
  • 一个T 类型和大小N 的数组是N-许多T 类型的对象放置在顺序内存中。仅仅因为您可以使指针指向该内存,并不能使数组成为指针。
  • 它们是不同的,因为c++是一种强类型语言,而sizeof特别指的是类型。有很多运行时情况,其中 a 和 p 可以互换使用(只要您保持在正确的范围内),但它们仍然是不同的类型。

标签: c++ arrays pointers


【解决方案1】:

经常听说数组名是指向内存块的常量指针

您经常被误导 - 或者您只是被误解了。数组不是指向内存块的常量指针。数组是一个包含一系列子对象的对象。所有对象都是一块内存。指针是一个包含对象地址的对象,即它指向该对象。

所以在下面的引用中,a 是一个数组,p 指向a 中的第一个子对象。

int a[10];

int * const p= a;

在某种意义上必须相等,因为 p 是指向与数组 a[] 相同的内存块的指针,并且不能更改为指向内存中的另一个位置。

如果这是你对相等的定义,那么它也适用于非数组对象:

char c;
int * const p = &c;

这里的p“指向与c相同的内存”,不能改为指向内存中的另一个位置。这是否意味着 char 对象与指针“相等”?不。数组也不是。

但是a(数组的名称)不就是指向数组同一个元素的常量指针吗?

不,数组的名称不是常量指针。就像char 的名称不是常量指针一样。

数组的名字是数组中第一个元素的地址,对吧?

让我们更笼统地说,这并不特定于数组。变量的名称“保存着变量命名的对象的地址”。该地址在运行时不会“保存”在内存中。它在编译时由编译器“持有”。当您对变量进行操作时,编译器会确保对位于正确地址的对象执行操作。

数组的地址始终与数组的第一个元素(子对象)所在的地址相同。因此,该名称确实 - 至少在概念上 - 拥有相同的地址。

如果我使用*(a+1),这与a[1] 相同,对吧? [错字修正]

没错。我将详细说明:在指针的情况下,一种只是另一种编写方式。哦,但是a 不是指针!这是一个问题:数组操作数被隐式转换为指向第一个元素的指针。这种隐式转换称为衰减。这是数组类型的特殊特性——它可能是最难理解指针和数组之间区别的特殊特性。

因此,即使数组的名称不是指针,它也可以衰减为指针。名称并不总是衰减为指针,只是在某些上下文中。当你使用operator[]时它会衰减,当你使用operator+时它会衰减。当您将数组传递给接受指向子对象类型的指针的函数时,它会衰减。当你使用sizeof 时它不会衰减,当你将它传递给一个通过引用接受数组的函数时它也不会衰减。

【讨论】:

  • 但是a(数组名)不就是指向数组同一个元素的常量指针吗?
  • @Arash No. 查看编辑。
  • @Arash 数组的名称被隐式转换为您正在考虑的常量指针。但它本身并不是一个指针。
  • 感谢您的 cmets。但我仍然很难理解一些东西。好的,数组不是指针。但是数组的名称包含数组中第一个元素的地址,对吗?如果我使用 *(a+1),这与 a[2] 相同,对吧?所以对我来说,数组似乎有点像指针。同样在我的示例中,我可以使用 p[2] 访问存储在 a[2] 中的值。所以指针和数组以某种方式相关,对吧?我在这里错过了什么?
  • @Arash 数组名在作为指针使用时转换为指针。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-08
  • 2012-11-17
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 2023-02-11
  • 1970-01-01
相关资源
最近更新 更多