将指向类型化/大小的枚举的指针转换为指向基础类型的指针是否安全?
Is it safe to convert a pointer to typed/sized enum to a pointer to the underlying type?
以下代码:
void f(const uint8_t* a) {} // <- this is an external library function
enum E : uint8_t { X, Y, Z };
int main(void) {
E e = X;
f(&e); // <- error here
}
生成以下错误:
/tmp/c.cc:10:3: error: no matching function for call to 'f'
f(&e);
^
/tmp/c.cc:5:6: note: candidate function not viable: no known conversion from 'E *' to 'const uint8_t *' (aka 'const unsigned char *') for 1st argument
void f(const uint8_t* e) { }
这让我感到惊讶,因为我认为枚举定义中的: uint8_t
意味着它们必须用该底层类型表示。我可以通过演员表轻松解决这个问题:
f((uint8_t*)&e);
我不太介意,但鉴于省略它是一个错误,这是否总是安全的,还是: uint8_t
没有提供我认为的保证?
它确实是安全的(虽然我不是语言律师):存储在内存中的是一个uint8_t
,这就是你要指向的。但是,如果f()
要获取指向非常量uint8_t
的指针,那么它可能会将值更改为未明确定义为E
枚举值之一的值。(编辑:)虽然这显然是C++标准允许的,但对许多人来说还是令人惊讶的(请参阅下面评论中关于这一点的讨论),我鼓励您确保它不会发生。
。但正如其他人所建议的那样,您获得错误并不是因为您的安全概念,而是因为隐式转换不是在指向类型之间执行的。您可以将E
传递给采用uint8_t
的函数,但不能将E *
传递给采用uint8_t *
的函数;根据语言委员会的说法,在我看来,这将是对指针类型的过于漫不经心的态度。
Afaik 这只是偶然合法的:
您正在做的是执行reinterpret_cast
,我假设f
正在内部取消引用该指针。这仅在非常有限的情况下是合法的,虽然不是规范性的,但 cppreference.com 很好地概述了这些情况:
当对动态类型为 DynamicType 的对象的指针或引用reinterpret_cast(或 C 样式强制转换)到对不同类型的 AliasedType 对象的指针或引用时,强制转换始终成功,但生成的指针或引用只能在满足以下条件之一时用于访问对象:
AliasedType 是(可能符合 cv 标准的)DynamicType
AliasedType 和 DynamicType 都是指向同一类型 T 的指针(可能是多级的,每个级别可能符合 cv 条件)(自 C++11 起)
AliasedType 是 DynamicType 的(可能符合 cv 标准的)有符号或无符号变体
- AliasedType 是 DynamicType
AliasedType 是一种聚合类型或联合类型,它将上述类型之一保存为元素或非静态成员(包括递归的子聚合元素和所包含联合的非静态数据成员):这使得在给定指向其非静态成员或元素的指针的情况下,可以安全地获取指向结构或联合的可用指针。
的基类(可能符合 cv 条件),DynamicType 是一个没有非静态数据成员的标准布局类,AliasedType 是它的第一个基类。
AliasedType 是 char、unsigned char 或 std::byte:这允许将任何对象的对象表示形式检查为字节数组。
如果 AliasedType 不满足这些要求,则通过新指针或引用访问对象将调用未定义的行为。这称为严格别名规则,适用于 C++ 和 C 编程语言。
这些情况都不包括强制转换为指向枚举基础类型的指针!
但是:
强制转换为指向unsigned char*
的指针并取消引用它始终是合法的,在大多数平台上,uint8_t
只是一个类型定义。所以在这种情况下没关系,但如果底层类型(例如)是uint16_t
,那就不行了。
话虽如此,听到大多数编译器允许这种使用,即使标准不允许,我也不会感到惊讶。
- 新分配指向函数的指针是否合法?
- 在函数结束后使用指向变量的指针是否安全?
- C++ 返回指向函数内定义的静态数组的指针是否有效?
- 经过最后一个数组元素末尾的指针是否应该等于超过整个数组末尾的指针?
- 传递给放置 new 的指针是否是指向其对象表示形式的非 UB 指针?
- 'this'指针是否可以在 c++ 标头声明中使用?
- C++ 在向量中使用指针是否可能导致指针悬空?
- 唯一指针是否在堆或堆栈上分配内存?
- 将基本实例指针强制转换为派生实例指针是否合法?(实例不是派生实例)
- 当向量增长时,指向向量元素的C++指针是否无效
- 如何判断指针是否是指向数组的指针
- 在类方法中使用 "this" 指针是否是一种好的做法?
- 如何知道指针是否已在其他地方释放
- 结构成员指针是否自动初始化为零?
- 为静态类创建指向对象的指针是否合法?
- 新的自动关键字指针是否会自行删除?
- 创建指针是否超过非数组指针的末尾,而不是从 C++17 中的一元运算符和未定义的行为派生?
- 检查指针是否指向矢量元素
- 如何创建一个带锁的指针数组并检查指针是否空闲?
- 在映射中插入更多元素后,指向 QMap 中元素的指针是否仍然有效?