优化和严格的混叠
我的问题是关于代码片段的问题,例如:
#include <iostream>
int main() {
double a = -50;
std::cout << a << "\n";
uint8_t* b = reinterpret_cast<uint8_t*>(&a);
b[7] &= 0x7F;
std::cout << a << "\n";
return 0;
}
据我所知,我没有违反任何规则,并且一切都很好地定义(如下所述,我忘记了uint8_t
不允许别名其他类型)。有一些实施定义的行为正在进行,但是出于这个问题的目的,我认为这是不相关的。
我希望此代码在double
遵循IEEE标准的系统上打印-50
,然后50
,是8 字节长,以小末日格式存储。现在的问题是。编译器是否可以保证这种情况发生。更具体地说,通过整个函数将
a
通过整个功能中的a
,可以显式或隐式地打开优化的编译器,以明确或隐式优化中间b [7]
。显然,可以通过指定挥发性双重A
来解决第二个问题,但这是需要的吗?
编辑:作为注释I(错误地)记住,uint8_t
被要求是无符号char
的别名,但实际上该标准并未指定此类。我还以一个方式写了一个问题,是的,是的,编译器可以提前知道这里的所有内容,但是修改为
#include <iostream>
int main() {
double a;
std::cin >> a;
std::cout << a << "\n";
unsigned char* b = reinterpret_cast<unsigned char*>(&a);
b[7] &= 0x7F;
std::cout << a << "\n";
return 0;
}
一个人可以看到问题可能出现的位置。这里不再违反严格的别名规则,a
不是编译时间常数。但是,理查德·克里特(Richard Critten)的评论很好奇是否可以检查并没有书写的别名数据,在仍然遵循标准的同时,是否有一种方法可以设置单个字节?
My question is regarding a code fragment, such as below:
#include <iostream>
int main() {
double a = -50;
std::cout << a << "\n";
uint8_t* b = reinterpret_cast<uint8_t*>(&a);
b[7] &= 0x7F;
std::cout << a << "\n";
return 0;
}
As far as I can tell I am not breaking any rules and everything is well defined (as noted below I forgot that uint8_t
is not allowed to alias other types). There is some implementation defined behavior going on, but for the purpose of this question I don't think that is relevant.
I would expect this code to print -50
, then 50
on systems where the double
follows the IEEE standard, is 8
bytes long and is stored in little endian format. Now the question is. Does the compiler guarantee that this happens. More specifically, turning on optimisations can the compiler optimise away the middle b[7]
, either explicitly or implicitly, by simply keeping a
in a register through the whole function. The second one obviously could be solved by specifying volatile double a
, but is that needed?
Edit: As an a note I (mistakenly) remembered that uint8_t
was required to be an alias for unsigned char
, but indeed the standard does not specify such. I have also written the question in a way that, yes the compiler can ahead of time know everything here, but modified to
#include <iostream>
int main() {
double a;
std::cin >> a;
std::cout << a << "\n";
unsigned char* b = reinterpret_cast<unsigned char*>(&a);
b[7] &= 0x7F;
std::cout << a << "\n";
return 0;
}
one can see where the problem might arise. Here the strict aliasing rule is no longer violated, and a
is not a compile time constant. Richard Critten's comment however is curious if the aliased data can be examined, but not written, is there a way one can set individual bytes, while still following the standard?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
编译器可以将双值50作为常数生成,并将其直接传递到输出函数。
B
可以完全优化。像大多数优化一样,这是由于AS-IF规则所致:从而阻止优化,通常将其视为与解决方案相反。
您没有提及您要问的编译器。我假设您的意思是标准是否保证了这一点。它不能保证这一点。您依靠有关实现的几个假设:
sizeof(double)&lt; 8
,然后您访问对象的范围,并且程序的行为不确定。std :: uint8_t
不是无符号char
的类型别名,则不允许Aliasdouble
和该程序不确定。鉴于假设的存在,因此behviour定义明确,因此第二个输出将为
double
值,就像-50,但其最重要的位(从8个向前)字节的位置(s)位置7将设置为0。如果Little Endian IEEE-754表示,则该值将为50。volatile
不需要保证这一点,并且在以防万一的情况下不会添加保证该程序的行为不确定。The compiler can generate the double value 50 as a constant, and pass that directly to the output function.
b
can be optimised away completely. Like most optimisation, this is due to the as-if rule:That would prevent the optimisation, which would generally be considered to be the opposite of a solution.
You didn't mention what compiler you are asking about. I'm going to assume that you mean whether the standard guarantees this. It doesn't guarantee that universally. You are relying on several assumptions about the implementation:
sizeof(double) < 8
, then you access the object outside of its bounds, and behaviour of the program is undefined.std::uint8_t
is not an a type alias ofunsigned char
, then it isn't allowed to aliasdouble
, and the behaviour of the program is undefined.Given the assumptions hold and thus behviour is well-defined, then the second output will be of a
double
value that is like -50, but whose most significant bit(s from 8th forward) of the byte at position 7 will have been set to 0. In case of little endian IEEE-754 representation, that value would be 50.volatile
is not needed to guarantee this, and it won't add a guarantee in case the behaviour of the program is undefined.