在C语言指针中,"p = (int[2]){*p};"这一行的意思是什么?

9

据我所理解,我将变量 a 的地址传递给函数 int ffx1

之后,这行代码 p = (int[2]){*p}; 到底意味着什么?

int ffx1(int * p)
{
    p = (int[2]){*p};
    return(p[1]);
}

int main()
{
    int a = 1;
    a = ffx1(&a);
    printf("%d", a);

   return 0;
}

5
(int[2]){*p}是复合字面量。例如,p = (int[2]){*p};可以将一个包含p所指向的值的长度为2的整数数组分配给p。另外,也可以使用类似于这样的方式int array[2] = {*p, 0}; p = array;来完成相同的操作。 - BLUEPIXY
@AndyG 是的,看看BLUEPIXY的评论。 - Jean-Baptiste Yunès
1
@coderredoc 终身 - EOF
@BLUEPIXY:如果可能的话,能否把这个写出来?这是一个值得讨论的好问题。 - user2736738
@BLUEPIXY 不是的。我在猜测为什么有人会认为这是 UB。 - EOF
显示剩余5条评论
2个回答

12

使用int ffx1(int * p)p是指向一个int的指针。

(int[2]){*p}是一个复合字面量,定义了一个由2个int组成的数组。@BLUEPIXY我们将这个无名数组称为X[2]。它的第一个元素的值为*p,而下一个元素,则作为一个int,会被初始化为0(§6.7.9 21&10),因为它没有被显式列出。

p = ....将指针p赋值为一个新值。在这种情况下,上述的数组X[]被转换为其第一个元素的地址或&X[0]

return p[1]解引用p,返回X[1]0中的值。


谢谢。你的答案是正确的。但是既然提到了p[1]和int[2],那么未命名数组的长度是多少?是2还是3? - hago
@hago 这个未命名的数组在这个答案中被称为 X[],由于 (int[2]) 的存在,它包含了两个元素。 - chux - Reinstate Monica
谢谢。解释得很好。但是在这里,我可以写 int *q = (int[2]){*p}; 而不是 p = (int[2]){*p}; 那么我的返回语句应该是什么呢?是 return p[1] 还是 q[1]?我猜应该是 q[1]。 - hago
@hago 是的,你可以写 int *q = (int[2]){*p} 来避免改变本地变量 preturn q[1] 将像上面一样工作。return p[1] 将使用原始传入的 p,它不指向 2 个元素。 - chux - Reinstate Monica
你为什么提到“全零位模式”?在这种情况下,它确实是正确的,因为int被定义为具有零值的所有零位模式;但是,如果它是指针数组,那么其他条目将获得空指针--不一定是全部为零。其他条目的初始化方式类似于{0} - M.M
@M.M "你为什么提到“全零位模式”?" --> 因为我记得在calloc()中,内存将被填充为全零位模式。然而,一般情况下非显式初始化可能不是全零位模式,就像你所说的那样 - 我已经修改了答案。 - chux - Reinstate Monica

9
这是一个指向复合字面量的指针。
C11-§6.5.2.5 复合字面量 (p9):

EXAMPLE 2 In contrast, in

void f(void)
{
int *p;
/*...*/
p = (int [2]){*p};
/*...*/
}

p is assigned the address of the first element of an array of two ints, the first having the value previously pointed to by p and the second, zero. The expressions in this compound literal need not be constant. The unnamed object has automatic storage duration.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接