阵列衰减和修改

Posted

技术标签:

【中文标题】阵列衰减和修改【英文标题】:Array decay and modification 【发布时间】:2019-08-10 02:04:52 【问题描述】:

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

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

C 的写法是第一个元素的地址 在计算数组表达式时计算。

这就是为什么你不能做类似的事情

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

因为在这种情况下,a 和 b 都计算为指针值;它是 相当于写 3 = 4。实际上内存中没有任何内容 存储数组中第一个元素的地址;编译器 只是在翻译阶段计算它1。

这是我感到困惑的时候。

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

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

我的问题是:

a = b 如何等同于3 = 4

会不会更类似于address of a = address of b

【问题讨论】:

评论不用于扩展讨论;这个对话是moved to chat。 【参考方案1】:

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

指针基础知识

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

要引用指针持有的地址处的值,您可以通过在指针名称前使用一元 '*' 字符取消引用指针。例如,b 持有a 的地址(例如b 指向a),因此要获取b 持有的地址的值,您只需取消引用 @987654340 @,例如*b.

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

数组在访问时转换为指针它的第一个元素

继续进行数组指针转换,C 和 C++ 标准都定义了 array type 在访问时如何转换为指针,但有 4 个例外。请注意,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;

并且,如 cmets 中提供的示例所述,如果允许,您将无法访问 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++ 标准定义转换的方式以及生成的指针类型不能被修改。 (所以简短的回答是因为标准说你不能)

仔细检查并确保它对您有意义并且已经深入人心。如果您仍然模糊,请发表评论。重要的部分是理解指针本身。对那些由数组/指针转换产生的指针可以做什么的限制是由标准本身决定的。

【讨论】:

以上是关于阵列衰减和修改的主要内容,如果未能解决你的问题,请参考以下文章

与蓝鸟的承诺链阵列

solidworks装配体中如何编辑阵列后的单个零件

TensorFlow 的学习效率的指数衰减法

RAID磁盘阵列

docker网络-2

创建Exchange2010的CAS阵列