C 是";int*ptr=*((&;a)和#x2B;1)&引用;其中;a「;int[5]在标准中定义得好吗?

C 是";int*ptr=*((&;a)和#x2B;1)&引用;其中;a「;int[5]在标准中定义得好吗?,c,arrays,pointers,language-lawyer,pointer-arithmetic,C,Arrays,Pointers,Language Lawyer,Pointer Arithmetic,根据这个问题()有一个关于这一行的答案(): int *ptr = (int*)(&a+1); 他说: 演员阵容(int*)隐藏了这个bug 因此,我得出以下结论: #include <stdio.h> int main( void ){ int a[5] = {1,2,3,4,5}; int *ptr = *( ( &a ) + 1 ); printf("%d", *(ptr-1) ); } 该标准是否定义明确 编辑: 在某个点上@c

根据这个问题()有一个关于这一行的答案():

int *ptr = (int*)(&a+1);
他说:

演员阵容(int*)隐藏了这个bug

因此,我得出以下结论:

#include <stdio.h>

int main( void ){
    int a[5] = {1,2,3,4,5};

    int *ptr = *( ( &a ) + 1 );
    printf("%d", *(ptr-1) );
}
该标准是否定义明确

编辑

在某个点上@chux指向
§6.3.2.3.7
,即:

但是我不确定我是否理解正确。

*(&a)+1)
是因为

。。。如果结果指向数组对象的最后一个元素后一个元素,则 不得用作已计算的一元
*
运算符的操作数。C11§6.5.6 8

(&a)+1
指向“过去一次”。在上面使用
*
会违反“不应”


即使
a
int a
,由于

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


此表达式调用未定义的行为作为取消引用运算符
*
的结果:

int *ptr = *( ( &a ) + 1 );
首先,让我们从
(&a)+1
开始。这部分是有效的<代码>&a具有类型
int(*)[5]
,即指向大小为5的数组的指针。通过添加1执行指针算术是有效的,即使
a
不是数组的元素

在详细说明添加剂操作员的第6.5.6节中,第7段规定:

在这些运算符中,指向以下对象的指针: 数组中的元素的行为与指向第一个元素的指针的行为不同 长度为1的数组的元素,其对象类型为 元素类型

它还可以创建一个指针,指向数组末尾的一个元素。因此
&a+1
是允许的

问题是当我们取消引用这个表达式时。第8段规定:

将具有整数类型的表达式添加到或减去时 对于指针,结果具有指针操作数的类型。如果 指针操作数指向数组对象的元素,数组 如果足够大,则结果将指向与 原始元素,例如 结果和原始数组元素等于整数表达式。 换句话说,如果表达式P指向 数组对象,表达式(P)+N(等价于N+(P))和(P)-N (其中,N的值为N)分别指向第i+N和 我−数组对象的第n个元素,前提是它们存在。此外,如果 表达式P指向数组对象的最后一个元素 表达式(P)+1指向数组对象最后一个元素的后面一个, 如果表达式q指向数组最后一个元素的后面 对象,表达式(Q)-1指向数组的最后一个元素 对象如果指针操作数和结果都指向元素 同一数组对象的,或超过数组最后一个元素的 对象时,评估不应产生溢出;否则 行为是未定义的如果结果指向最后一个元素上方一个 对于数组对象,它不能用作一元
*
已评估的运算符。

由于不允许取消对超过数组末尾的指针的引用,因此beahvior是未定义的

返回引用文章中的表达式:

int *ptr = (int*)(&a+1);
printf("%d %d", *(a+1), *(ptr-1));
这也是未定义的行为,但原因不同。在这种情况下,将
int(*)[5]
转换为
int*
,然后使用转换后的值。使用这种转换值合法的唯一情况是将对象指针转换为字符类型的指针,例如
char*
unsigned char*
,然后取消引用以读取对象表示的字节

编辑:

看起来上面的两条线实际上是很明确的。当指针取消引用
*(ptr-1)
发生时,正在访问的对象具有有效类型
int
,该类型与取消引用的
ptr-1
类型相匹配。将指针值
&a+1
int(*)[5]
强制转换为
int*
是有效的,对强制转换的指针值执行指针算术也是有效的,因为它指向
a
内部或一个元素经过它。

int*ptr=*(&a)+1)

C11-§6.5.6“加法运算符”(第8页):

在指针中添加或减去整数类型的表达式时 结果具有指针操作数的类型如果指针操作数指向 数组对象,并且数组足够大,结果指向从 原始元素,使得结果和原始元素的下标不同 数组元素等于整数表达式。换句话说,如果表达式
P
指向 数组对象的
i
-第个元素,表达式
(P)+N
(等价地,
N+(P)
)和
(P)-N
(其中
N
的值为
N
)分别指向
i+N
-th和
i−第n个元素
数组对象,前提是它们存在。此外,如果表达式
P
指向最后一个 数组对象的元素,表达式
(P)+1
指向 数组对象,如果表达式
Q
指向最后一个元素o之后的一个
int a[5] = {1,2,3,4,5};
int *ptr = *( ( &a ) + 1 );
int *ptr = *( ( &a ) + 1 );
int *ptr = (int*)(&a+1);
printf("%d %d", *(a+1), *(ptr-1));