有没有合法的方法将 unsigned char 指针转换为 std::byte 指针?
Posted
技术标签:
【中文标题】有没有合法的方法将 unsigned char 指针转换为 std::byte 指针?【英文标题】:Is there a legal way to convert a unsigned char pointer to std::byte pointer? 【发布时间】:2018-09-05 22:49:28 【问题描述】:我使用STB 库将图像加载到内存中。具体函数stbi_load
返回一个指向unsigned char
的指针,这是一个数组。
我很想对原始数据使用新的 C++17 API,std::byte
,这将使我更具表现力,让我可以逐个像素地为原始数据设置别名,或者通过投射来逐个颜色地为原始数据设置别名它到不同的数据类型(不同大小的整数)。
现在我尝试了这个:
std::unique_ptr<std::byte[], stbi_deleter>(stbi_load(...));
当然因为没有隐式转换所以没用。
然后我尝试了:
std::unique_ptr<std::byte[], stbi_deleter>(
static_cast<std::byte*>(stbi_load(...))
);
再次,它仍然没有工作。我不得不决定改用reinterpret_cast
。让我质疑这种转换是否合法。我可以合法地将unsigned char*
转换为std::byte*
根据严格的别名规则吗?然后我可以将数据转换为另一种数据类型,如std::uint32_t*
并对其进行变异吗?这也会打破别名规则吗?
【问题讨论】:
我还没有看到任何适用于 std::byte 的实用程序。有没有人有一个很好的例子来说明它可能有用的地方? > “这将使我更有表现力,并让我逐个像素地为原始数据起别名。”我很确定那仍然是UB。 to_integer() 基本上只是 memcpy 的一个包装器。 请注意,unsigned char
数组已经非常适合逐像素访问数据。 (不确定你所说的“别名”是什么意思)。 std::byte
的优势在于减少您在某些类型的算术中意外使用它的可能性,并且正如您所提到的,更清楚地表达了数据的性质。
@NeilButterworth 我认为与使用unsigned char
相比,它的主要目的是禁用隐式转换
@NeilButterworth 它的用处很薄但不缺;即使只是查看流式传输(与使用语义重载char
时所需的体操相比)本身就是一个好处。可以说。我想说这主要是一个自我记录的事情。
【参考方案1】:
严格的别名规则从不禁止任何指针转换。它是关于访问对象的表达式的类型。
std::byte
可以别名任何其他类型,这在您链接的 cppreference 页面以及标准中的严格别名规则(C++17 basic.lval/8.8)中有所提及。所以可以使用reinterpret_cast<std::byte *>
,然后读写unsigned char
的数组。
如果您使用uint32_t
类型的表达式来读取或写入unsigned char
的数组,这将违反严格的别名规则。
【讨论】:
【参考方案2】:我可以根据严格的别名规则合法地将 unsigned char* 转换为 std::byte* 吗?
是的,这就是为什么std::byte
“继承”自unsigned char
。但是你必须通过reinterpret_cast<>
,就像将任意类型转换为char*
或unsigned char*
时一样。
然后我可以将数据转换为另一种数据类型,如 std::uint32_t* 并对其进行变异。
没有。你不能用std::byte
做任何你不能用char*
或unsigned char*
做的事情。
std::byte
的主要用途似乎是拥有可以同时具有字符串和原始数据重载的函数。
此外,它消除了以下烦恼:
char val = foo();
std::cout << (int)val << "\n";
【讨论】:
std::byte
当然不会从unsigned char
继承,如果除了这样的事情之外没有其他原因是不可能的。后者是前者的底层类型,然而,它是一个作用域枚举。
(诚然,从宏观上看,这种区别在很大程度上是学术性的)
unsigned char
是std::byte
的基础类型无关紧要,因为在任一方向上都不允许枚举与其基础类型之间的别名。相反,通过std::byte
访问任何对象都有特定的限制。以上是关于有没有合法的方法将 unsigned char 指针转换为 std::byte 指针?的主要内容,如果未能解决你的问题,请参考以下文章