c – 布尔值是否应在分配时被截断为true或false?
作者:互联网
我发现存储在bool变量(btw Visual-C和clang)中的值存在差异,如果存储的值既不是true也不是false(如果它以某种方式被破坏),我不确定是否这是一个Visual-C错误,或者如果它只是UB我应该忽略.
请参考以下示例:
#include <cstdint>
#include <iostream>
#include <string>
#include <limits>
bool inLimits(bool const v)
{
return (static_cast<std::int32_t>(v) >= static_cast<std::int32_t>(std::numeric_limits<bool>::min()) && static_cast<std::int32_t>(v) <= static_cast<std::int32_t>(std::numeric_limits<bool>::max()));
}
int main()
{
bool b{ false };
bool const* const pb = reinterpret_cast<bool const*>(&b);
std::uint8_t * const pi = reinterpret_cast<std::uint8_t*>(&b);
std::cout << "b: " << b << " pb: " << (*pb) << " pi: " << std::to_string(*pi) << std::endl;
std::cout << "b is " << (inLimits(b) ? "" : "not ") << "in numeric limits for a bool" << std::endl;
*pi = 3; // Simulate a bad cast during boolean creation
bool const b2{ b };
bool const b3{ *pb };
std::cout << "b: " << b << " pb: " << (*pb) << " pi: " << std::to_string(*pi) << std::endl;
std::cout << "b2: " << b2 << " b3: " << b3 << std::endl;
std::cout << "b is " << (inLimits(b) ? "" : "not ") << "in numeric limits for a bool" << std::endl;
std::cout << "b2 is " << (inLimits(b2) ? "" : "not ") << "in numeric limits for a bool" << std::endl;
std::cout << "b3 is " << (inLimits(b3) ? "" : "not ") << "in numeric limits for a bool" << std::endl;
return 0;
}
这是Visual-C的输出
b: 0 pb: 0 pi: 0
b is in numeric limits for a bool
b: 3 pb: 3 pi: 3
b2: 3 b3: 3
b is not in numeric limits for a bool
b2 is not in numeric limits for a bool
b3 is not in numeric limits for a bool
这是铿锵的输出
b: 0 pb: 0 pi: 0
b is in numeric limits for a bool
b: 1 pb: 1 pi: 3
b2: 1 b3: 1
b is in numeric limits for a bool
b2 is in numeric limits for a bool
b3 is in numeric limits for a bool
在按值构造新的布尔值时,以及当它与流运算符一起使用时,看起来在clang中存在限制检查.
我应该忽略这一点,还是仅仅是Visual-C的错误?
谢谢!
编辑:
对于那些不了解样本目的的人来说,它只是一个“模拟”内存损坏或代码的另一部分中的错误的展示,导致布尔值被初始化为除了true或false之外的其他东西,无论如何布尔的二进制表示.
(我想知道是否必须使用断言来保护我的代码不被其他地方的不当使用,但仅当此行为不是UB时)
第二次编辑:
添加了numeric_limits代码.
解决方法:
该标准没有规定bool的价值表示是什么.编译器可以自由地制定自己的规范.
您的证据表明VC要求true表示为LSB集,而clang允许任何非零表示为真.
对于VC,您的代码会在行bool const b2 {b};上导致未定义的行为,特别是当它尝试从b中读取值时.在b的存储器中设置的位不对应于b的值,并且标准没有定义在这种情况下发生的情况,因此它是未定义的行为.
当未定义的行为发生时,没有任何保证;程序的所有输出都没有意义.根据在此点之后(甚至在它之前,实际上)出现的输出语句,您无法推断任何内容.
标签:bounds,c,boolean,visual-c,clang-2 来源: https://codeday.me/bug/20190823/1700670.html