如何在 C 中将 2d 数组作为参数发送给需要 1d 数组的函数?

0jn*_*ts3 0 c arrays pointers function

这是 KN King 所著《C 编程:现代方法》一书中的练习

“假设以下数组包含一周的每小时温度读数,每行包含一天的读数: int temperatures[7][24]; 编写一条语句,使用搜索函数在整个温度数组中搜索值 32。”

下面的代码包括之前练习中的搜索函数,以及我调用该函数的 main() 函数。搜索只是处理一个数组并检查是否有任何元素等于提供的参数“key”。该解决方案似乎编译并执行预期的输出,它打印“找到 32”,或者如果我注释掉分配则不打印任何内容temperatures[5][22] = 32;

请注意该函数如何获取一维数组,但练习要求处理二维数组。

我最初尝试了这个解决方案,在函数调用中没有显式类型转换(int *),并在编译时得到了这个(我对其进行了一些重新格式化):

1 编译器警告:“从不兼容的指针类型传递搜索参数 1”

1 注意:“预期为‘const int *’,但参数的类型为‘int * [24]’”

为什么会出现警告/注释?如果存在不兼容,为什么它们不是错误?类型转换为 int* 消除了任何编译问题,但该解决方案实际上是正确/安全的还是我对 C 的理解/实践不好?我知道该函数需要 int* 但二维数组会衰减为 int * [24] 类型的指针,而无需进行类型转换。然而,代码在任何一种情况下都有效,尽管我只有一个测试用例。我怎样才能修改我的解决方案逻辑来完全避免这个问题?不过,搜索功能应该保持不变。

#include <stdbool.h>
#include <stdio.h>

bool search(const int a[], int n, int key);

int main(void){

    int temperatures[7][24] = {0};
    temperatures[5][22] = 32;
    bool has32 = search((int*)temperatures, 7 * 24, 32);

    if(has32)
        printf("32 was found");
    return 0;
}

bool search(const int a[], int n, int key){

    const int *p;

    for(p = a; p < a + n; p++)
        if(*p == key)
            return true;
    return false;
}
Run Code Online (Sandbox Code Playgroud)

All*_*ind 5

传递第一个元素的地址,但将数组索引到列索引 23 之后是技术上未定义的行为:

bool has32 = search(&temperatures[0][0], 7 * 24, 32);
Run Code Online (Sandbox Code Playgroud)

更好的选择是更改原型search()以使用 VLA:

bool search(size_t rows, size_t cols, const int a[rows][cols], int key) {
    for(size_t r = 0; r < rows; r++)
        for(size_t c = 0; c < cols; c++)
            if(a[r][c] == key)
               return true;
    return false;
}
Run Code Online (Sandbox Code Playgroud)

并这样称呼它:

    bool has32 = search(
        sizeof(temperatures) / sizeof(*temperatures),
        sizeof(*temperatures) / sizeof(**temperatures),
        temperatures,
        32
    );
Run Code Online (Sandbox Code Playgroud)