带指针的 const 结构,丢弃不带警告的限定符

const struct with pointer, discarded qualifier without warning

提问人:pschulz 提问时间:10/22/2022 更新时间:10/22/2022 访问量:68

问:

我有一个带有指向某物的指针的结构。我期望通过指向结构的 const-struct 的指针访问此指针会给我一个指向 const-something 的指针。但在这种情况下,gcc 不会产生警告:

#include <stdlib.h>    
    
struct S {    
    void* ptr;    
};    
    
struct S* create(void)    
{    
    struct S* S = malloc(sizeof(*S));    
    S->ptr = malloc(sizeof(int));    
    return S;    
}    
    
void some_func(void* p);    
    
int main(void)    
{    
    struct S* S = create();    
    const void* ptr = S->ptr;    
    const struct S* SC = S;    
    some_func(ptr); // warning as expected    
    some_func(SC->ptr); // no warning    
} 

所以实际上是一个?我一直以为,但现在我很困惑。在这种情况下是否有可能收到警告?SC->ptrconst void*

c GCC 警告

评论


答:

5赞 Eric Postpischil 10/22/2022 #1

SC->ptr是一个 .它不是 or .void * constconst void *const void * const

const struct S* SC = S;定义为指向 -Qualified 的指针。结构是合格的这一事实意味着您不应修改结构。该结构包含 类型的成员。由于结构是 -qualified,因此其成员是 -qualified。这意味着您不应该更改 .其类型为 。SCstruct Sconstconstptrvoid *constconstptrvoid * const

但是,这并不影响指向的内容。无论自身是否是 -限定的,它都指向 ,而不是 。ptrptrconstvoidconst void

C 标准没有提供处理结构的多个版本的好方法,其中一个版本具有指向非类型的成员,而另一个版本具有指向类型的成员。通常,没有好的方法可以将一种这样的结构转换为另一种类型。constconst

评论

0赞 pschulz 10/22/2022
谢谢,从来没有这样想过,这个推理很有道理。
1赞 John Bollinger 10/22/2022 #2

那么SC->ptr真的是吗?const void*

不。 是指定 类型的对象的表达式,不能使用该表达式来修改该对象的值。(原则上,可能有其他表达式指定可以修改它的同一对象。这与 a 类似,但不完全相同 -- 指针不能修改。修改它所指向的数据没有任何意义。SC->ptrvoid *void * const

    some_func(SC->ptr); // no warning    

[...]

在这种情况下是否有可能收到警告?

C 语义没有提供特别的理由来诊断有关该情况的任何可疑或错误,因为同样,不能修改的是指针,而不是它指向的数据。而且由于指针是按值传递的,因此函数无法对其进行修改。