数组订阅是否算作对象的地址? [英] Does array subscription count as taking address of object?

查看:96
本文介绍了数组订阅是否算作对象的地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题的灵感来自此问题的答案.

以下代码可能会导致不确定的行为:

Following code has potential for undefined behaviour:

uint64_t arr[1]; // Uninitialized
if(arr[0] == 0) {

C标准指定具有自动存储期限的未初始化变量具有不确定值,该值可以是 unspecified trap表示形式.它还指定uintN_t类型没有填充位,并且值的大小和范围得到了很好的定义;因此无法使用uint64_t的陷阱表示形式.

C standard specifies that uninitialized variable with automatic storage duration has indeterminate value, which is either unspecified or trap representation. It also specifies that uintN_t types have no padding bits, and size and range of values are well defined; so trap representation for uint64_t is not possible.

因此,我得出结论,未初始化的值本身不是未定义的行为.怎么读?

So I conclude that uninitialized value itself is not undefined behavior. What about reading it?

6.3.2.1左值,数组和函数指示符

  1. ...
  2. 除非它是sizeof运算符的操作数,_Alignof运算符,一元&运算符,++运算符,--运算符或的左操作数.运算符或赋值运算符,将不具有数组类型的左值转换为存储在指定对象中的值(不再是左值);这称为左值 转换. ...

  1. ...
  2. Except when it is the operand of the sizeof operator, the _Alignof operator, the unary & operator, the ++ operator, the -- operator, or the left operand of the. operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue); this is called lvalue conversion. ...

... 如果 左值表示可以使用寄存器存储类声明的自动存储持续时间的对象(从未获取其地址),并且该对象未初始化(未使用初始化程序声明并且未对其执行赋值操作)使用之前),行为是不确定的.

... If the lvalue designates an object of automatic storage duration that could have been declared with the register storage class (never had its address taken), and that object is uninitialized (not declared with an initializer and no assignment to it has been performed prior to use), the behavior is undefined.

问题:下标数组是否算作接收对象的地址?

Question: Does subscripting array count as taking the address of an object?

下面的文字似乎暗示下标数组需要转换为指针,这似乎不可以不使用地址来完成:

Following text seems to imply that subscripting array requires conversion to a pointer, which seems impossible to do without taking address:

6.5.2.1数组下标

约束

  1. 其中一个表达式的类型应为要完成对象类型的指针",另一个则应为 表达式应为整数类型,结果应为类型".
  1. One of the expressions shall have type ‘‘pointer to complete object type’’, the other expression shall have integer type, and the result has type ‘‘type’’.

语义

  1. 后缀表达式后跟方括号[]是表达式的下标 数组对象元素的指定.下标运算符的定义[] 是E1 [E2]等于(*((E1)+(E2)))).由于转换规则 如果E1是数组对象,则适用于二进制+运算符(等效于指向 数组对象的初始元素),并且E2是整数,E1 [E2]将E2指定为E1的元素(从零开始计数).
  1. 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- the element of E1 (counting from zero).

这使§6.3.2.1第3段看起来很奇怪.如果订阅需要转换为指针,数组怎么可能根本拥有寄存器存储类?

This makes §6.3.2.1 paragraph 3 seem weird. How could array have register storage class at all, if subscription requires conversion to a pointer?

推荐答案

是的,根据您在6.5.2.1中引用的部分,数组下标应计为地址.表达式E1必须具有其地址.

Yes, array subscripting counts as taking the address, as per the part you quoted in 6.5.2.1. The expression E1 must have its address taken.

因此,6.3.2.1中UB的特殊情况不适用于数组索引.如果使用数组索引,则是否可以使用register存储持续时间存储该数组无关紧要(具有其地址的变量不能使用register存储持续时间).

Therefore the special case of UB in 6.3.2.1 does not apply to array indexing. If array indices are used, it is not relevant if the array could be stored with register storage duration or not (a variable having its address taken cannot use register storage duration).

您正确的假设是,读取具有不确定值的未初始​​化stdint.h类型(其地址已占用)不会调用未定义的行为(由C11 7.20.1.1保证),但只是未指定行为.该值可以是任何值,并且在多次读取之间可以是不确定的,但不能是陷阱.

You are correct in assuming that reading an uninitialized stdint.h type with indeterminate value, which has its address taken, does not invoke undefined behavior (guaranteed by C11 7.20.1.1), but merely unspecified behavior. The value could be anything and it can be non-deterministic between several reads, but it cannot be a trap.

读取未初始化的变量始终是UB"是一个广为人知的错误说法. 此答案.

"Reading an uninitalized variable is always UB" is a wide-spread but incorrect myth. Further information with normative sources in this answer.

这篇关于数组订阅是否算作对象的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆