c++ - 阵列衰减和修改

标签 c++ arrays

在阅读了一些关于为什么C / C++中的数组是不可修改的左值的答案之后,我仍然有些困惑。

根据公认的答案(总结如下):Why array type object is not modifiable?

C is written in such a way that the address of the first element would be computed when the array expression is evaluated.

This is why you can't do something like

int a[N], b[N];
a = b;

because both a and b evaluate to pointer values in that context; it's equivalent to writing 3 = 4. There's nothing in memory that actually stores the address of the first element in the array; the compiler simply computes it during the translation phase1.



这是我感到困惑的时候。

当我们有了a = b时,我觉得b应该衰减为一个指向b的第一个元素的指针值。

我认为a也会衰减为指针值,但是我不确定。

我的问题是:
a = b如何等效于3 = 4

它会更类似于address of a = address of b吗?

最佳答案

由于在最后几个问题上可衡量的程度,您对数组/指针转换的困惑似乎是由于难以理解指针本身而造成的。让我们从快速总结开始。

指针基础知识

指针只是一个普通变量,将其他地址作为其值。换句话说,指针指向可以找到其他内容的内存地址。通常情况下,您会想到一个包含立即值的变量,例如int a = 5;,指针将仅保存5存储在内存中的地址。要声明一个指针本身并分配一个地址作为其值,可以使用一元'&'运算符获取该类型的现有对象的地址。例如,int *b = &a;接受a的地址(其中5存储在内存中),并将该地址分配为指针b的值。 (b现在指向a)

要引用指针所保存地址的值,可以通过在指针名称之前使用一元'*'字符来取消引用指针。例如b保留a的地址(例如b指向a的地址),因此要获取b所保存的地址的值,您只需取消引用b即可,例如*b

无论对象的类型如何,指针算术都以相同的方式工作,因为指针的type控制着指针算术,例如:如果使用char *指针,则pointer+1指向下一个字节(下一个char),对于int *指针(通常为4个字节的整数),pointer+1将指向下一个int,位于pointer之后4个字节的偏移处。 (因此,一个指针只是一个指针。...算术由type自动处理)

数组是访问指针的第一个元素转换为指针

继续进行数组指针转换,C和C++标准都定义了如何在存在4个异常的情况下将array type转换为访问时的指针。请注意,此处的C++标准将依赖于“基本类型”的C标准,并将在C++标准中添加定义以在必要时扩展C标准。数组/指针转换的基本行为由C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)提供

§ 6.3.2 Other operands
    6.3.2.1  Lvalues, arrays, and function designators
    Array pointer conversion
    (p3) Except when it is the operand of the sizeof operator, the _Alignof 
    operator, or the unary '&' operator, or is a string literal used to 
    initialize an array, an expression that has type "array of type" is 
    converted to an expression with type "pointer to type" that points to 
    the initial element of the array object and is not an lvalue.


该标准专门定义了数组在访问转换为指向第一个元素的指针时所产生的指针不是左值。 。因此,如果您拥有数组a和数组b,则该标准本身禁止您使用以下方法更改该指针所持有的地址:
a = b;

并且,如注释中提供的示例中所述,如果允许,将导致您失去访问a元素的能力。

C++标准合并了C标准中定义的行为,但是随后扩展了数组/指针转换周围的定义,以解决对C中不存在的类型和对象的使用,但不更改6.3.2.1(p3)的行为。

C++ Standard 7.3.2 Array-to-pointer conversion提供:

§ 7.3.2 Array-to-pointer conversion
  1  An lvalue or rvalue of type “array of N T” or “array of unknown bound of T” 
     can be converted to a prvalue of type “pointer to T”. The temporary 
     materialization conversion ([conv.rval]) is applied. The result is a 
     pointer to the first element of the array.


该扩展是C++标准,专门将结果指针定义为prvalue - pure rvalue,而不是C定义的“非左值”,并添加了“T的未知边界数组”语言。

因此,在C和C++中,在访问时,数组都将转换为指向其第一个元素的指针(受§6.3.2.1(p3)枚举的4个异常的影响),并且所得的指针无法修改或分配给另一个地址。修改的限制与普通指针的行为没有任何关系,而仅仅是由于C / C++标准定义转换的方式,并且不能修改结果指针类型。 (所以简短的答案是因为标准规定您不能这样做)

仔细检查并确保它对您有意义并沉入其中。如果您仍然很模糊,请发表评论。重要的部分是理解指针本身。数组/指针转换对那些指针的处理方式的限制由标准本身决定。

关于c++ - 阵列衰减和修改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57438758/

相关文章:

java - Java排序测试-

python - 通过函数传递多维 Numpy 数组并将结果保存在 CSV 文件中

c++ - 在 clang 中实例化后的静态成员初始化

php.net 的 PHP 开始标签

c++ - 如何在 QT 中查看和存储来自设备的数据?

objective-c - 将 char 输入复制到字符串数组中

c - 二维数组结构段错误

c++ - Linux 中的 OpenCV:无法获取 Mat 大小(cv::Size),仅返回 MSize

c++ - 如何通过 `friend` 将流运算符<<放在模板化类主体之外?

无法读取数字字符频率