为什么这段代码有效?常量数组上的 memcpy

Why this code works ? memcpy on a constant array

memcpy的参数是memcpy(void *_Dst, const void *_Src, size_t _Size)

但是使用下面的代码,我传递了一个常量数组作为参数“_Src”,它仍然将数组的内容复制到目标中,即使我没有传递 const void *

int tab[3] = { 1, 2, 3 };
    
memcpy(tab, (int[3]) { 7, 8, 9 }, sizeof(int) * 3);
    
printf("%d %d %d \n", tab[0], tab[1], tab[2]); // Output: 7 8 9

表达式 (int[3]) { 7, 8, 9 } returns 是指向数组第一个元素的指针吗?

当函数的参数声明为指向 const 类型的指针时,它“阻止”函数修改指针指向的内容(即不通过参数本身,但它可以通过强制转换), 但不限制实参类型为const.

const限定类型的变量可以安全地转换为const限定类型。根据 C standard:

的第 6.3.2.3p2 节,这是允许的

For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal

这个

(int[3]) { 7, 8, 9 }

int[3] 类型的复合文字,用作函数参数,隐式转换为指向其第一个元素的指针。

另一方面(C 标准,6.3.2.3 指针)

1 A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer.

2 For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.

所以在这次通话中

memcpy(tab, (int[3]) { 7, 8, 9 }, sizeof(int) * 3);

复合字面量首先转换为 int * 类型的指针,指向其第一个元素,然后根据第一个引号转换为 void * 类型,然后转换为 const void * 根据第二个引用。

限定符const表示指向的对象在函数内不会改变。并不意味着用作参数的表达式是常量表达式。