英文:
Issue with UBA sanitizer casting negative double to unsigned long long on C++
问题
我一直在使用C++,并且一直在使用UBA sanitizer将double转换为unsigned long long。然而,当值为负数时,我遇到了一个问题,导致错误消息:“运行时错误:值-2超出了类型'long long unsigned int'可表示值的范围。”
代码大致如下:
unsigned long long valueULL = 0;
double value = -2;
valueULL = (unsigned long long)value;
我尝试使用这个强制转换,但没有帮助:
valueULL = std::make_unsigned_t
是否有一种方法可以在不遇到此错误的情况下进行强制转换?
英文:
I've been working with C++ and have been utilizing the UBA sanitizer to convert a double to an unsigned long long. However, I've been encountering an issue when the value is negative, which results in the error message: "runtime error: value -2 is outside the range of representable values of type 'long long unsigned int'"
The code is something like this:
unsigned long long valueULL = 0;
double value = -2;
valueULL = (unsigned long long)value;
I tried to use this cast instead and it doesn't help:
valueULL = std::make_unsigned_t<unsigned long long>(value);
Is there a way to cast it without encountering this error?
答案1
得分: 1
看起来你正在提到clang的-fsanitize=undefined
UBSanitizer。
在这种情况下,这个检测器是正确的,你的代码确实包含未定义行为:
浮点类型的prvalue可以转换为整数类型的prvalue。
这个转换会截断,即舍弃小数部分。
如果截断后的值无法表示为目标类型,行为将是未定义的。
- [conv.fpint] §1
你可以通过两步转换来修复未定义行为:
double value = -2;
auto valueULL = static_cast<unsigned long long>(static_cast<long long>(value));
或者,你可以调用std::llround
:
auto valueULL = static_cast<unsigned long long>(std::llround(value));
注意:这将产生一个非常大的值,即ULLONG_MAX - 2
。如果这正是你想要的,那么这些解决方案是有意义的。
否则,你应该听从检测器的建议,并确保在转换为unsigned
类型之前,你的double
不会变成负数。
英文:
It seems that you're referring to clang's -fsanitize=undefined
UBSanitizer.
The sanitizer is correct in this case, and your code really does contain undefined behavior:
> A prvalue of a floating-point type can be converted to a prvalue of an integer type.
The conversion truncates; that is, the fractional part is discarded.
The behavior is undefined if the truncated value cannot be represented in the destination type.
You can fix your undefined behavior with a two-step cast:
double value = -2;
auto valueULL = static_cast<unsigned long long>(static_cast<long long>(value));
Or alternatively, you could call std::llround
:
auto valueULL = static_cast<unsigned long long>(std::llround(value));
Note: this will produce a very great value, namely ULLONG_MAX - 2
. If this is what you actually want, then these solutions make sense.
Otherwise, you should listen to the sanitizer and make sure that your double
doesn't turn negative before converting to unsigned
types.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论