在 C 中将指针传递给数组的正确方法是什么?

What is the proper way of passing pointers to arrays in C?

以这段代码为例:

#include <stdio.h>
void print_array(size_t size, unsigned (*myarray)[])
{
    printf("Array size: %lu\n", size);
    for (size_t i = 0; i < size; ++i)
            printf("%u ", (*myarray)[i]);
    printf("\n");
}
int main() {
    unsigned myarray[] = { 9, 8, 7, 6, 5 };
    print_array(sizeof(myarray) / sizeof(unsigned), &myarray);
    return 0;
}

使用 clang 分析器(通过 gcc 10.1.0)编译时,警告为:

src/main.c:7:3: warning: 2nd function call argument is an uninitialized value
            printf("%u ", (*myarray)[i]);
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~

输出为:

Array size: 5
9 8 7 6 5 

这段代码有什么错误,在 C 中将指针传递给数组的正确方法是什么?

您可以简单地传递一个指针并使用数组变量表示其第一个元素开始的地址这一事实。 似乎将 pedantic 与 clang 一起使用,对函数参数 可能 指向什么做出了很多假设,所以它抱怨。

void print_array(size_t size, const unsigned *myarray)
{
    printf("Array size: %lu\n", size);
    for (size_t i = 0; i < size; ++i)
            printf("%u ", myarray[i]);
    printf("\n");
}

int main() {
    unsigned myarray[] = { 9, 8, 7, 6, 5 };
    print_array(sizeof(myarray) / sizeof(unsigned), myarray);
    return 0;
}

这似乎是误报。代码没问题——虽然风格有点奇葩,但都是valid C.

如果评论是关于实际缺少初始化的,则可能与该工具没有检查调用者有关。但是,即使分析器只考虑本地翻译单元,它也不能关闭并假设默认情况下传递的变量未初始化。那将是一个非常奇怪的假设。

也许分析器吓坏了,因为您实际上将 unsigned (*myarray)[5] 传递给期望 unsigned (*myarray)[] 的函数(指向不完整类型的指针,未指定大小的数组)。您可以尝试将参数更改为 unsigned (*myarray)[size]) 并查看它是否会使工具更快乐。

编辑:虽然数组指针类型是兼容的,因此该工具也不应因此而抱怨。根据 C17 6.7.6.2/6,一种或两种数组类型可以省略大小说明符并且仍然兼容:

For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value.