gpt4 book ai didi

c++ - 经过最后一个数组元素末尾的指针是否等于经过整个数组末尾的指针?

转载 作者:行者123 更新时间:2023-12-02 07:28:53 25 4
gpt4 key购买 nike

编译器在编译代码时会出现分歧

int main()
{
constexpr int arr[3] = {};
static_assert((void*)(arr + 3) == (void*)(&arr + 1));
}

在 GCC 和 Clang 中,static_assert 不会触发,MSVC 认为 static_assert 失败 https://godbolt.org/z/dHgmEN

(void*)(arr + 3) == (void*)(&arr + 1) 的计算结果应该为 true 吗?为什么?

最佳答案

最新标准草案中的相关规则:

[intro.object]

Objects can contain other objects, called subobjects. A subobject can be a member subobject ([class.mem]), a base class subobject ([class.derived]), or an array element. An object that is not a subobject of any other object is called a complete object.

因此,数组元素是子对象。示例中的数组是一个完整的对象。

<小时/>

[expr.eq]

... Comparing pointers is defined as follows:

  • If one pointer represents the address of a complete object, and another pointer represents the address one past the last element of a different complete object,79 the result of the comparison is unspecified.

  • Otherwise, if ... both represent the same address, they compare equal.

79) As specified in [basic.compound], an object that is not an array element is considered to belong to a single-element array for this purpose

第一个案例看起来几乎匹配,但又不完全匹配。 两者都是指向不同完整对象最后一个元素的指针 - 一个完整对象是数组 arr,另一个是假设的单元素数组,其元素是 arr。并且也不是指向可能存在于各自数组之后的不相关完整对象的指针,如以下 [basic.compound] 引用中的注释所澄清。

因此,假设它们代表相同的地址,则应适用另一种情况。

<小时/>

[basic.compound]

A value of a pointer type that is a pointer to or past the end of an object represents the address of the first byte in memory ([intro.memory]) occupied by the object43 or the first byte in memory after the end of the storage occupied by the object, respectively. [ Note: A pointer past the end of an object ([expr.add]) is not considered to point to an unrelated object of the object's type that might be located at that address. A pointer value becomes invalid when the storage it denotes reaches the end of its storage duration; see [basic.stc]. — end note ]

For purposes of ... comparison ([expr.rel], [expr.eq]), a pointer past the end of the last element of an array x of n elements is considered to be equivalent to a pointer to a hypothetical array element n of x and an object of type T that is not an array element is considered to belong to an array with one element of type T. ...

43) For an object that is not within its lifetime, this is the first byte in memory that it will occupy or used to occupy.

arr 和仅包含 arr 的假设数组具有相同的地址和相同的大小。因此,超过两个数组的一个元素被认为相当于数组边界之外同一地址的指针。

<小时/>

需要明确的是,数组不能包含填充:

[expr.sizeof]

... When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array. The result of applying sizeof to a potentially-overlapping subobject is the size of the type, not the size of the subobject. When applied to an array, the result is the total number of bytes in the array. This implies that the size of an array of n elements is n times the size of an element.

<小时/>

让我们澄清一下,转换为 void* 不应更改指针值,从而更改相等性。

[conv.ptr]

A prvalue of type “pointer to cv T”, where T is an object type, can be converted to a prvalue of type “pointer to cv void”. The pointer value ([basic.compound]) is unchanged by this conversion.

关于c++ - 经过最后一个数组元素末尾的指针是否等于经过整个数组末尾的指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59710209/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com