微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

如何解决将结构传递给 `const struct` 类型的参数不会产生警告

在下面的示例中,非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,mem};

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

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

解决方法

转换指针

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

如果表示被调用函数的表达式的类型确实包含原型,则参数会被隐式转换,就像通过赋值一样,转换为相应参数的类型......

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

……左操作数具有原子、限定或非限定指针类型,并且……两个操作数都是指向兼容类型的限定或非限定版本的指针,并且左侧指向的类型具有指向的类型的所有限定符正确的……

此外,在 C 2018 6.3.2.3 中讨论了指针的转换,其中第 2 段说:

对于任何限定符q,指向非q限定类型的指针可以转换为指向q限定类型的指针类型的版本...

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

const 应用于结构

我知道结构声明中的 const 应用于其字段......

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

脚注

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。