c - 数组订阅是否算作获取对象的地址?

标签 c arrays language-lawyer

这个问题的灵感来自 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

  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. 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

  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’’.

Semantics

  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-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/

相关文章:

c - C与其抽象机之间的确切关系是什么?

css - 为什么 CSS 命名的网格区域不在引号中?

c - MPI 使用 MPI_Send 和 MPI_Reduce 发送消息

fork() 上的 C 段错误(核心转储)

arrays - 无法分配给属性 : 'itemArray' is a get-only property

javascript - 循环/迭代要返回的对象数组和字符串数组 - Javascript

arrays - C 中函数参数中的固定数组或指针之间的区别?

c++ - 如何解决 linux 定时器信号处理程序

Java Arrays.equals() 为二维数组返回 false

c++ - 值初始化是 C++98 标准的一部分吗?如果不是,为什么在 C++03 标准中添加它?