指向限定和非限定类型表示的指针

Pointer to qualified and non-qualified type representation

本文关键字:表示 指针 类型      更新时间:2023-10-16

将指向非限定类型的指针重新解释为指向限定类型的指针安全吗?考虑一个包含指针成员"void *ptr"的标准布局类型和另一个定义为"const void *ptr"的标准布局类型。这些类型的布局是否兼容,这个答案是否取决于语言版本或C和c++之间?

动机:

有时在与C程序接口时,定义一个结构体,将参数分组到某种类型的缓冲区。为了const正确性,输入缓冲区应该有指向底层缓冲区的const指针,但输出缓冲区显然必须是可变的。

struct s1 { const void *ptr; }
struct s2 { void *ptr; }
const void *get_in_ptr(void);
void *get_out_ptr(void);
void alg(const s1 *in, const s2 *out);
void f()
{
    s1 in_arg = { get_in_ptr() };
    s2 out_arg1 = { get_out_ptr() };
    s2 out_arg2 = { get_out_ptr() };
    /* First algorithm pass. */
    alg(&in_arg, &out_arg1);
    /* Second algorithm pass. */
    alg((const s1 *)&out_arg1, &out_arg2); /* Is this legal? */
}

请在任何答案中引用相关标准出版物

C11 states:

对于任何限定符q,指向非q限定类型的指针都可以转换为指向该类型的q限定版本的指针;存储在原始指针中的值与转换后的指针中的值比较一致。

因此,强制转换为限定版本是安全的,反之则不然。抛出-特别是const或volatile可以使用不同的内存访问,例如,在哈佛体系结构中将const变量存储在程序内存(PIC, AVR)中。而且标准对后果也很清楚:

如果试图通过使用非const限定类型的左值来修改用const限定类型定义的对象,则行为未定义。如果试图通过使用非易失性限定类型的左值来引用由易失性限定类型定义的对象,则该行为是未定义的。

简单地说:一般来说,抛弃这些限定符并不是是安全的。但是,标准没有提到ex- const对象的读访问。

其他限定符和进一步的细节,请阅读自己。


对于结构布局:C使用类型/布局的兼容性,而不是c++。因此,如果两种类型使用相同的布局/标准类型,而不是相同的类型名称,则它们是兼容的。

[C99: 6.2.5/25, C11: 6.2.5/26]: [.]一个类型的限定或不限定版本是属于同一类型类别的不同类型,具有相同的表示和对齐要求。 [. .]

[C++03, C++11, C++14: 3.9.3/1]: […]一个类型的cv-限定或cv-不限定版本是不同的类型;但是,它们应具有相同的表示和对齐要求(3.11)。

对于封装类型:

[C99: 6.2.7/1]: […]]此外,在单独的翻译单元中声明的两个结构类型、联合类型或枚举类型,如果它们的标签和成员满足以下要求,则它们是兼容的:如果其中一个使用标签声明,则另一个也应使用相同的标签声明。如果两者都是完整类型,则适用以下附加要求:它们的成员之间必须有一对一的对应关系,以便每一对对应的成员都用兼容的类型声明,并且如果对应对中的一个成员用名称声明,则另一个成员也用相同的名称声明。 [. .]

[C++03: 9.2/14]:如果两个POD-struct (clause 9)类型具有相同数量的非静态数据成员,则它们是布局兼容的,并且相应的非静态数据成员(按顺序)具有布局兼容的类型(3.9)。

[C++11: 9.2/16, C++14: 9.2/17]:如果两个标准布局结构(第9条)类型具有相同数量的非静态数据成员,并且相应的非静态数据成员(按声明顺序)具有布局兼容类型(3.9),则它们是布局兼容的。

因此,假设我们忽略了类型系统绕过(const void*void*const_cast,直接或通过c风格强制转换-注意reinterpret_cast与此无关,并且明确禁止删除cv-限定符),只讨论混叠兼容性…

……是的,这就是"safe"。

这就是为什么我们能够巧妙地使用const_cast,当古老的C api强迫我们相信他们的话,而不是实际使用const -safety。

你知道这是可以的,因为当你写&in_arg时,你的编译器隐式地将s1*转换为const s1*进行调用,并且没有抱怨。