这个问题的灵感来自 answers to this question .
以下代码可能会出现未定义的行为:
uint64_t arr[1]; // Uninitialized
if(arr[0] == 0) {
C 标准指定具有自动存储持续时间的未初始化变量具有不确定值,即未指定 或陷阱表示。它还指定 uintN_t 类型没有填充位,并且值的大小和范围定义明确;所以 uint64_t
的陷阱表示是不可能的。
所以我得出结论,未初始化的值本身并不是未定义的行为。阅读它怎么样?
###6.3.2.1 Lvalues, arrays, and function designators
- ...
- 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. 3. 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. If the array object has register storage class, the behavior is undefined.
问题:下标数组算作取对象地址吗?
下面的文字似乎暗示下标数组需要转换为指针,如果不获取地址,这似乎是不可能的:
###6.5.2.1 Array subscripting Constraints
- 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’’.
Semantics
- 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).
这使得 §6.3.2.1 第 3 段看起来很奇怪。如果订阅需要转换为指针,数组怎么可能有寄存器存储类?
最佳答案
是的,根据您在 6.5.2.1 中引用的部分,数组下标算作获取地址。表达式 E1
必须使用它的地址。
因此 6.3.2.1 中 UB 的特殊情况不适用于数组索引。如果使用数组索引,则数组是否可以使用 register
存储期限存储是不相关的(已获取其地址的变量不能使用 register
存储期限)。
您假设读取具有不确定值的未初始化 stdint.h
类型是正确的,它的地址已被占用,不会调用未定义的行为(由 C11 7.20 保证) .1.1),但仅仅是未指定的行为。该值可以是任何值,并且在多次读取之间可以是不确定的,但不能是陷阱。
“读取未初始化的变量总是 UB”是一个广为流传但不正确的神话。 有关规范来源的更多信息,请参阅 this answer .
关于c - 数组订阅是否算作获取对象的地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47884469/