将指向数组的指针转换为指针 [英] casting pointer to array into pointer

查看:161
本文介绍了将指向数组的指针转换为指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下C代码:

int arr[2] = {0, 0};
int *ptr = (int*)&arr;
ptr[0] = 5;
printf("%d\n", arr[0]);

现在,很明显,该代码在普通编译器上显示5.但是,有人可以在C标准中找到指定该代码确实有效的相关部分吗?还是代码未定义行为?

Now, it is clear that the code prints 5 on common compilers. However, can somebody find the relevant sections in the C standard that specifies that the code does in fact work? Or is the code undefined behaviour?

我要问的是为什么&arr投射到void *时为什么与arr投射到void *时一样?因为我认为代码等效于:

What I'm essentially asking is why &arr when casted into void * is the same as arr when casted into void *? Because I believe the code is equivalent to:

int arr[2] = {0, 0};
int *ptr = (int*)(void*)&arr;
ptr[0] = 5;
printf("%d\n", arr[0]);

我在思考以下问题时发明了该示例: Pointer-到阵列的重叠末端 ...但这显然是一个不同的问题.

I invented the example while thinking about the question here: Pointer-to-array overlapping end of array ...but this is clearly a distinct question.

推荐答案

对于联合和结构,请参见. ISO 9899:2011§6.7.2.1/16f:

For unions and structures, cf. ISO 9899:2011§6.7.2.1/16f:

16工会的规模足以容纳其最大的成员.成员中最多一个的值可以随时存储在并集对象中.指向经过适当转换的并集对象的指针指向其每个成员(或者,如果一个成员是位字段,则指向它所驻留的单元),反之亦然.

16 The size of a union is sufficient to contain the largest of its members. The value of at most one of the members can be stored in a union object at any time. A pointer to a union object, suitably converted, points to each of its members (or if a member is a bit-field, then to the unit in which it resides), and vice versa.

17在结构对象中,非位字段成员和位字段所在的单元的地址按照声明的顺序增加.指向经过适当转换的结构对象的指针指向其初始成员(或者,如果该成员是位字段,则指向它所驻留的单元),反之亦然.结构对象中可能有未命名的填充,但在其开头没有.

17 Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

对于数组类型,情况要复杂一些.首先,从ISO 9899:2011§6.2.5/20观察数组是什么:

For array types, the situation is a bit more complex. First, observe what an array is, from ISO 9899:2011§6.2.5/20:

数组类型描述了具有特定成员对象类型(称为元素类型)的连续分配的非空对象集.只要指定了数组类型,元素类型就应该是完整的.数组类型通过其元素类型和数组中元素的数量来表征.数组类型据说是从其元素类型派生的,并且如果其元素类型是 T ,则有时该数组类型是 称为" T 的数组".从元素类型构造数组类型的过程称为数组类型派生".

An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. The element type shall be complete whenever the array type is specified. Array types are characterized by their element type and by the number of elements in the array. An array type is said to be derived from its element type, and if its element type is T, the array type is sometimes called "array of T". The construction of an array type from an element type is called "array type derivation".

措辞连续分配"表示数组成员之间没有填充.脚注109确认了这一概念:

The wording "contiguously allocated" implies that there is no padding between array members. This notion is affirmed by footnote 109:

两个对象可能在内存中相邻,这是因为它们是较大数组的相邻元素或结构的相邻成员之间没有填充,或者是由于实现方式选择放置它们,即使它们是不相关的.如果先前的无效指针操作(例如,在数组范围之外进行访问)产生了未定义的行为,则后续的比较也会产生未定义的行为.

Two objects may be adjacent in memory because they are adjacent elements of a larger array or adjacent members of a structure with no padding between them, or because the implementation chose to place them so, even though they are unrelated. If prior invalid pointer operations (such as accesses outside array bounds) produced undefined behavior, subsequent comparisons also produce undefined behavior.

在6.5.3.5节(示例2)中使用sizeof运算符表示要在数组之前或之后也没有填充:

The use of the sizeof operator in §6.5.3.5, Example 2 expresses the intent that there is also no padding before or after arrays:

示例2

sizeof运算符的另一个用途是计算元素数量 在一个数组中:

Another use of the sizeof operator is to compute the number of elements in an array:

sizeof array / sizeof array[0]

因此,我得出结论,指向数组的指针(转换为指向该数组的元素错字的指针)指向数组中的第一个元素.此外,请注意关于指针的平等性定义(第6.5.9/6/6f条):

I therefore conclude that a pointer to an array, converted to a pointer to the element typo of that array, points to the first element in the array. Furthermore, observe what the definition of equality says about pointers (§6.5.9/6f.):

6当且仅当两个都是空指针时,两个指针比较相等,两个都是指向同一个对象的指针(包括指向一个对象和它的开始处的子对象的指针)或函数,两个都是指向最后一个元素之后的指针相同的数组对象,或者一个是指针 指向一个数组对象的末尾,另一个指向另一个数组对象的开始的指针,该指针恰好紧随地址空间中的第一个数组对象. 109)

6 Two pointers compare equal if and only if both are null pointers, both are pointers to the same object (including a pointer to an object and a subobject at its beginning) or function, both are pointers to one past the last element of the same array object, or one is a pointer to one past the end of one array object and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space.109)

7就这些运算符而言,指向不是数组元素的对象的指针的行为与指向长度为1的数组的第一个元素的指针的行为相同,而对象的类型为其元素类型

7 For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

由于数组的第一个元素是开头的子对象",所以指向数组的第一个元素的指针和指向数组的指针比较相等.

Since the first element of an array is "a subobject at its beginning," a pointer to the first element of an array and a pointer to an array compare equal.

这篇关于将指向数组的指针转换为指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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