我有一个(char*)缓冲区。我可以做以下事情吗:
-
int8_t i8 = *(int8_t*)buffer;
-
int16_t i16 = *(int16_t*)buffer;
-
float f = *(float*)buffer;
-
int8_t i = 22; *(int8_t*)buffer = i
-
int16_t i = 25; *(int16_t*)buffer = i
-
float f = 16.4; *(float*)buffer = f
编辑:让我们假设缓冲区是通过以下方式之一创建的:
char* buffer = new char[300 * sizeof(char)];
char* buffer = (char*)malloc(300 * sizeof(char));
对于带有new
的版本,它们都不能保证在所有可能的实现上都没有未定义的行为:
int8_t
不是char
或signed char
(但在我所知的所有平台上都是),则是一种混叠冲突(因此是未定义的行为)。如果在两者之间不给
buffer[0]
赋值,它也会读取一个不确定的值,这也会导致未定义的行为。如果
int16_t
不是char
或signed char
,则也是一种混叠冲突,这在任何具有CHAR_BIT == 8
的普通平台上都是不可能的。buffer[0]
的初始化再次丢失。保证是混叠冲突。
与1相同。减去不确定价值问题。
与2相同。减去不确定价值问题。
与3相同。
对于带有malloc
的版本,假设您只访问过带有的buffer
,则以下情况成立:您列出的类型中只有一种:
4.、5.和6。假设指向类型的CCD_ 21至多为CCD_。
1.,2。和3.:在上述条件下,这些都是允许的,并且假设您实际上以4.、5.中的方式写入缓冲区。或6首先匹配类型。
请注意,您可以在std::launder
的帮助下修复new
案例中的问题,使其等效于malloc
案例。
还要注意,malloc
的情况之所以有效,是因为malloc
被指定为隐式创建隐式生存期类型的对象,并返回指向这些创建的对象中合适对象的指针。所有标量类型都是隐式生存期类型,这意味着您列出的所有类型也是。
通过使用placementnew来创建要显式存储在缓冲区中的对象,在这里不犯错误会容易得多。placement new返回一个指向新创建的对象的指针,您可以在不进行任何强制转换的情况下使用该对象。
所有这些都不允许用一种类型写入缓冲区,然后用另一种类型读取,或者用不同类型写入同一缓冲区位置。如果没有新的或类似的放置来更改类型(并重新初始化值!),那么无论如何,这都将是一种混叠冲突。对于不同类型的位间转换表示,请改用std::bit_cast
。(也许C++23中的std::start_lifetime_as
也有帮助。)