这两种形式的指针参数语法真的相同吗?

ale*_*ari 1 c arrays pointers

我知道在 C 中,当涉及到指针参数时,我们有两种不同类型的语法。我只是想知道它们是否真的一样。考虑这个小程序,其中我有两个函数 fx1 和 fx2,它们采用具有不同 sintax 的指针参数:

void fx1( int* p ){

    *p = 10;

}

void fx2( int p[] ){

    *p = 10;

}

int main(){

    int a = 20;
    
    fx1(&a);
    fx2(&a);

Run Code Online (Sandbox Code Playgroud)

Eri*_*hil 5

它们并不完全相同。考虑这段代码:

\n
typedef struct foo T;\n\nvoid fx1(T *p)  { }\nvoid fx2(T p[]) { }\n
Run Code Online (Sandbox Code Playgroud)\n

编译此函数时,Clang 毫无怨言地接受第一个函数,但报告第二个函数 \xe2\x80\x9carray 具有不完整的元素类型“T”(又名“struct foo”)\xe2\x80\x9d。

\n

这是因为根据 C 2018 6.7.6.2 1,数组的元素类型必须具有完整类型,并且 Clang 在 C 2018 6.9.1 7 中将数组参数调整为指针的规则之前应用该规则。

\n

当然,在不完成类型 的情况下,第一个函数无法对p指向 的内容进行操作。但是,这种情况可能会出现在仅将指针传递给知道完整类型的其他函数的函数中,或者在将指针转换为不同类型的函数中。例如,传递给的比较例程可以声明为,但不能声明为。*pTqsortint compare(const void *a, const void *b);int compare(const void a[], const void b[]);

\n

一个更神秘的区别是数组语法允许这样做:

\n
void fx2(int p[static 3]);\n
Run Code Online (Sandbox Code Playgroud)\n

这表示传递给的参数p必须指向至少三个元素。指针参数没有对应的语法。

\n

随之而来的是一个更深奥的差异:

\n
void fx2(int p[foo()]) {}\n
Run Code Online (Sandbox Code Playgroud)\n

这名义上声明p为一个具有可变数量元素的数组,并且指针参数没有相应的语法。p而且这很麻烦,因为 C 标准并不清楚从数组到参数的调整是否发生在foo()表达式求值之前。Clang 评估它,而 GCC 不评估它。

\n

除上述问题外,调整后的参数p与的fx2参数相同。pfx1

\n