简体   繁体   English

是否将 C++ 引用从 unsigned char 转换为 double& 安全?

[英]Is casting a C++ reference from unsigned char to double& safe?

I am trying to implement a "table" of references for setting various code elements by an index lookup.我正在尝试通过索引查找来实现用于设置各种代码元素的引用“表”。 Most of the underlying variables are double , but a few are different types like unsigned char .大多数基础变量都是double ,但有一些是不同的类型,如unsigned char

Here is a simplified example:这是一个简化的示例:

static unsigned char foo = 0;     // Variable to set
static unsigned double bar = 0.0; // Variable to set
...
struct tableEntry {
    double& ref; // Reference to one of the above
    double min;
    double max;
};
struct tableEntry entries[] {
    { bar, 0.0, 1.0 },
    { (double&)foo, 0x0, 0xff },
};

When attempting to assign bar via the table, everything is fine.尝试通过表格分配栏时,一切正常。

entries[0].ref = 1.0;

This results in entries[0].ref == 1.0 , and bar == 1.0 , as expected.正如预期的那样,这会导致entries[0].ref == 1.0bar == 1.0 However, when assigning foo via the table...但是,当通过表分配 foo 时......

entries[1].ref = 1.0;

This results in a value mismatch somehow, as if the reference is not able to be interpreted correctly, or isn't even referring to the right object.这会以某种方式导致值不匹配,就好像引用无法正确解释,或者甚至没有引用正确的对象。 After this assignment, entries[1].ref == 1 , but foo == 0 .在此分配之后, entries[1].ref == 1 ,但foo == 0

Is this undefined behavior by the language, or am I misusing or abusing something?这是语言的未定义行为,还是我滥用或滥用某些东西? It's possible it is a discrepancy in versions of the standard, as I tested a similar example on repl.it with C++17 and it worked as I was expecting.这可能是标准版本的差异,因为我用 C++17 在 repl.it 上测试了一个类似的例子,它按我的预期工作。 This is not working as expected when compiling with our target compiler using mex in MATLAB, using Visual Studio 2017 as the compiler.使用 MATLAB 中的mex ,使用 Visual Studio 2017 作为编译器使用我们的目标编译器进行编译时,这无法按预期工作。

Reading an individual char as a double is undefined behavior as it breaks type aliasing rules, which is what you are doing.将单个char读取为double是未定义的行为,因为它违反了类型别名规则,这就是您正在做的事情。 Converting from a char value to a double value using static_cast<double> is perfectly normal and defined though.使用static_cast<double>char值转换为double值是完全正常和定义的。

It is generally possible to reinterpret double as char , but only in specific scenarios:通常可以将double重新解释为char ,但仅限于特定场景:

Type aliasing类型别名

Whenever an attempt is made to read or modify the stored value of an object of type DynamicType through a glvalue of type AliasedType, the behavior is undefined unless one of the following is true:每当尝试通过 AliasedType 类型的泛左值读取或修改 DynamicType 类型的对象的存储值时,除非满足以下任一条件,否则行为未定义:

  • [...] [...]
  • AliasedType is std::byte (since C++17), char , or unsigned char : this permits examination of the object representation of any object as an array of bytes. AliasedType 是std::byte (C++17 起)、 charunsigned char :这允许检查任何对象作为字节数组的对象表示。

(See reinterpret_cast conversion ) (见reinterpret_cast转换

So we are allowed to examine a double (DynamicType) as a char[] (AliasedType), but not the other way around.因此,我们可以将double (DynamicType) 视为char[] (AliasedType),但不能反过来。 Consider the fact that char is exactly one byte large and double will most likely be 8 bytes large.考虑到char正好是 1 个字节大而double很可能是 8 个字节大的事实。 What is the value of the remaining 7 bytes when reinterpreting references?重新解释引用时剩余 7 个字节的值是多少? It is undefined.它是未定义的。

Note that when casting references, a C-style cast like (double&) is equivalent to reinterpret_cast<double&> .请注意,在转换引用时,像(double&)这样的 C 样式转换等效于reinterpret_cast<double&> I recommend using the explicit C++ casts like const_cast , reinterpret_cast and static_cast to avoid confusion.我建议使用显式 C++ 强制const_cast ,如const_castreinterpret_caststatic_cast以避免混淆。

Alas strict aliasing applies to references in a similar way to which it applies to pointers.唉,严格别名应用于引用的方式与应用于指针的方式类似。

The behaviour of making use of the reference attained with (double&)foo is undefined .利用(double&)foo获得的引用的行为是undefined

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM