我被要求在一次面试中给出以下代码的输出。
int a[] = {1,2,3,4,5};
int *p = &a + 1;
printf("%d, %d", *(a+1), *(p - 1));我说我不能确定第二次面试的结果,所以我没有通过面试。
当我回到家,尝试编译代码时,g++会报告一个错误,但gcc只会给出一个警告。打印的结果是'2,5‘。
有人知道为什么C和C++编译器在这一点上表现不同吗?
发布于 2012-02-21 00:17:23
a是一个整数数组,它在需要时转换为指向第一个元素的指针。a+1调用该转换,并提供指向第二个元素的指针。
&a是指向数组本身的指针,而不是指向数组第一个元素的指针,因此&a + 1指向数组末尾之外(如果是二维数组,则指向第二个数组所在的点)。
然后,代码将该指针(类型为int (*)[5])转换为指向整数(类型为int*)的指针。在没有显式reinterpret_cast的情况下,C++不允许这样的转换,而C在它允许的指针转换方面则更为宽松。
最后(假设p和p2是一回事),p - 1指向a的最后一个元素。
发布于 2012-02-21 00:10:17
a是包含5个整数的数组,所以&a是指向包含5个整数的数组的指针。在C++中,如果不强制转换地址,则无法在int*中分配地址。gcc ( C语言)只给出了警告,但我认为这不是有效的C。
对于代码:
&a+1是a之后的下一个数组,即a中第6个元素的地址,因此p-1是a中第5个元素的地址。
(我不确定&a+1是否合法。它是在数组之后的元素的地址,这通常是合法的,但是因为&a不是数组,所以它可能是非法的。)
发布于 2012-02-21 00:06:39
int a[] = {1,2,3,4,5};
int *p = &a + 1;这是无效的C代码。
表达式&a + 1的类型为int (*)[5]。不能将int (*)[5]类型的表达式分配给int *。
除了泛型对象指针类型void *之外,对象指针之间没有隐式转换。使用&a + 1值初始化p需要强制转换。
C在哪里说这个声明是无效的?
int *p = &a + 1;在赋值运算符的约束中:
(C99,6.5.16.1p1)“两个操作数都是指向兼容类型的限定或非限定版本的指针,左边指向的类型具有右边指向的类型的所有限定符”
int和数组类型是不兼容的类型(有关类型兼容性的更多信息,请参阅6.2.7p1 )。
另外,它是一个初始化,而不是赋值,但同样的约束也适用:
(C99,6.7.8p11)“标量的初始值设定项应该是单个表达式,可选括在大括号中。对象的初始值是表达式的初始值(转换后);应用与简单赋值相同的类型约束和转换,将标量的类型作为其声明类型的非限定版本。”
https://stackoverflow.com/questions/9364199
复制相似问题