将结构传递给“const struct”类型的参数不会产生警告

Passing structure to parameter of type `const struct` does not produce a warning

在下面的示例中,非 const 限定指针 b 被传递给 func,它需要一个指向 const 限定类型的指针。因此,我希望编译器发出警告。但是,如果我用 clang 和 -Wall -Wextra -pedantic 编译这个程序,则没有警告。这是为什么?

#include <stdlib.h>
#include <string.h>
#define N 5


struct Bear {
    int n;
    int v;
    int *data;
};


void func (const struct Bear *bear, int *data, const size_t n)
{
    memcpy (bear->data, data, n);    
}


int main (void)
{
    int arr[N];
    int *mem = malloc (N*sizeof (int));
    if (mem == NULL) return -1;

    struct Bear *b = &(struct Bear){1, 2, mem};
    func (b, arr, N);

    free (mem);
    return 0;
}

此外,如果我将初始化结构的行更改为

const struct Bear *b = &(const struct Bear){1, 2, mem};

仍然没有警告。我知道结构声明中的 const 应用于其字段,因此 func 中的 bear->v = 11; 显然是一个错误(并产生警告)。然而,对于指针来说,这似乎并非如此。

这是未定义的行为吗?我在这里错过了什么?

转换指针

当调用带有原型的函数时,参数(b,类型struct Bear *)被转换为相应参数的类型(bear,类型const struct Bear *),根据 C 2018 6.5.2.2 7:

If the expression that denotes the called function has a type that does include a prototype, the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters…

6.5.16.1 1 中的赋值约束包括允许转换为指向相同类型但添加限定符的指针,例如 const:

… the left operand has atomic, qualified, or unqualified pointer type, and … both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right…

此外,C 2018 6.3.2.3 中讨论了指针的转换,其中第 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…

很简单,限定词就是对一个事物的使用限制;他们说它是为该事物的某些潜在用途而设计的。 const 限定符表示该对象将仅用于读取其值,而不用于修改其值。1 因此将指针传递给 可以修改为表明它不会修改的函数。所以 C 标准的规则是允许这样做的。

const 应用于结构

I understand that const in a struct declaration is applied to its fields…

如果结构是const,结构成员dataconst,但那个成员是一个指针。所以这只是意味着 指针 const。这并不意味着它指向的是const

脚注

1 const 限定符并不是修改对象的完全障碍。如果一个对象是在没有 const 的情况下定义的,则可以将指向它的指针(已为其添加 const )转换(通过强制转换)回没有 const 的指针并用于修改对象.