正如问题标题所示,将2 ^ 31分配给有符号和无符号的32位整数变量会产生意外结果.
这是C++我做的简短程序(in ),看看发生了什么:
#include <cstdio>
using namespace std;
int main()
{
unsigned long long n = 1<<31;
long long n2 = 1<<31; // this works as expected
printf("%llu\n",n);
printf("%lld\n",n2);
printf("size of ULL: %d, size of LL: %d\n", sizeof(unsigned long long), sizeof(long long) );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是输出:
MyPC / # c++ test.cpp -o test
MyPC / # ./test
18446744071562067968 <- Should be 2^31 right?
-2147483648 <- This is correct ( -2^31 because of the sign bit) …Run Code Online (Sandbox Code Playgroud) 我准备一个非常棘手的c#考试,这个问题突然出现了.我有以下代码:
uint zzz = -12u;
Run Code Online (Sandbox Code Playgroud)
-12u被识别为System.Uint32文字,但它只能存储在类型的变量中long.这是为什么 ?
相关段落可在C90 ISO 9899:1990中找到6.1.2.5类型:
"[..]涉及无符号操作数的计算永远不会溢出,因为[...]"
因此9899:1990 6.3不能适用,因此不能是未定义的行为.
感谢Keith Thompson帮助我阅读.:-)
[2014-03-14]显然无符号短整数可能会溢出,导致未定义的行为,具体取决于目标环境.如果短无符号整数被算术提升为int,则会发生这种情况.详细信息请参阅更新的答案和supercat的评论.感谢两者.:-)
首先,抱歉我的英语不好......我尽我所能.这是我的第一个问题,我认为这是一个非常愚蠢的问题.
由于一些可悲的原因,我的公司仍然坚持ANSI C90(ANSI/ISO 9899:1990),所以我手中有这个标准的旧版本,但仍然缺少更正和修正.
我有一个非常简单的问题,并且在我学习的时候已经完全知道了答案 - 直到我尝试在标准中阅读它.
如果我在添加上有无符号整数溢出会发生什么.请看这段代码:
uint32_t a,b,c;
b = UINT_MAX;
c = UINT_MAX;
a = b + c; /* Overflow here - undefined behavior? */
Run Code Online (Sandbox Code Playgroud)
我所知道的就是,只要需要,无符号整数就会包裹起来,一切都很好,但并非总是如此.
现在我正在寻找标准中的相应部分.
当然,ISO 9899:1990 6.2.1.2描述了无符号整数的转换,无论何时转换.还有一点6.2.1.5"通常的算术转换",它描述了类型如何变得更宽,主要是表达式的两个操作数具有相同的类型.
现在有6.3个"表达式"与我有关.我引用:
"[......]如果在评估表达式期间发生异常(即,如果结果未在数学上定义或不在其类型的可表示的范围内),则行为不明确.[...]"
关于加法运算符的第6.3.6章说:
没有任何说法,结果值被转换为结果类型 - 因此6.2.1.2不适用.但是价值明显溢出,其中6.3步.
据我所知 - 根据ISO 9899:1990,这是未定义的行为.我错过了什么?Corrigendae中有什么东西吗?我错过了标准中的一行或一行吗?
我现在真的很困惑.:-)
关于,马克
[2014-03-03]解决了
[2014-03-03] 感谢Acme我现在对ANSI C99有一个清晰而完整的答案(参见答案: "无符号整数减法定义的行为":明确定义的行为如预期的那样 …
我正在尝试在VHDL中使用具有良好定义的位宽的无符号整数.似乎VHDL不喜欢我试图将文字值分配给定义为:
variable LCD_DATA: unsigned(19 downto 0) := 0;
Run Code Online (Sandbox Code Playgroud)
但是在我的IDE(Quartus)中,我得到一个投诉"UNSIGNED类型与整数文字不匹配".我还抱怨将数字添加到这样定义的类型中.我需要做出的首选改变是什么?
我正在关注原始数据类型的Java教程.早期,它说明了这一点
在Java SE 8及更高版本中,您可以使用int数据类型来表示无符号的32位整数,其最小值为0,最大值为2 ^ 32-1.使用Integer类将int数据类型用作无符号整数.
我从这句话中理解的是,只要我使用Integer包装器对象而不是int原始数据类型,我现在可以存储最多2 ^ 32-1作为int.但是当我尝试这个时,我的编译器抱怨我使用的值太大,2 ^ 31.我已经尝试使用原始数据类型和Object.
Integer integerObjectLarge = 2147483648; //2^31
int integerPrimitiveLarge = 2147483648; //2^31
Run Code Online (Sandbox Code Playgroud)
我究竟如何使用int/Integer存储无符号值,例如2 ^ 31?
我想看看当unsigned long long被分配了一个值的幕后发生了什么unsigned int.我做了一个简单的C++程序来尝试它并将所有io移出main():
#include <iostream>
#include <stdlib.h>
void usage() {
std::cout << "Usage: ./u_to_ull <unsigned int>\n";
exit(0);
}
void atoiWarning(int foo) {
std::cout << "WARNING: atoi() returned " << foo << " and (unsigned int)foo is " <<
((unsigned int)foo) << "\n";
}
void result(unsigned long long baz) {
std::cout << "Result as unsigned long long is " << baz << "\n";
}
int main(int argc, char** argv) {
if (argc != 2) usage();
int …Run Code Online (Sandbox Code Playgroud) 在业余时间,我一直在研究一个实用程序库,除其他外,它支持有符号/无符号的128位整数.在某些情况下,此库使用cpu-dispatching来使用simd指令,但需要可移植的后备,因此它将在其他任何地方运行.最近我实现了128位移位的便携式回退.它运行正常并且运行速度相当快,但它没有我想要的那么快,尤其是在32位架构上.
这是一个带有所有相关类型和功能的剥离版本(包括完整性的64位版本):
typedef uint32_t UInt32;
typedef int32_t Int32;
typedef uint64_t UInt64;
typedef int64_t Int64;
// Returns 0xFFFFFFFF if value != 0, otherwise returns 0.
UInt32 AllOrNothingMask32(Int32 value)
{
return UInt32(-Int32(value != 0));
}
struct alignas(16) UInt128
{
// Ensure the layout matches the architecture.
// LE = little endian
// BE = big endian
#if CPU_TYPE == CPU_LE32
UInt32 mLow;
UInt32 mLowMid;
UInt32 mHighMid;
UInt32 mHigh;
#elif CPU_TYPE == CPU_BE32
UInt32 mHigh;
UInt32 mHighMid;
UInt32 mLowMid;
UInt32 mLow;
#elif CPU_TYPE …Run Code Online (Sandbox Code Playgroud) 我希望or在 2 位图上执行简单的逻辑,但 Swift 认为这是错误的:
let u: UInt8 = 0b1
let i: Int = 0b10
i | u // Binary operator '|' cannot be applied to operands of type 'Int' and 'UInit8'
Run Code Online (Sandbox Code Playgroud)
有什么方法可以符合类型推断并且仍然有效吗?
我总是可以这样做i | Int(u) // 3,但我认为这并不是最佳选择。
我在编写一个程序试图打印 UTF-8 字符的组成字节值时遇到了这个问题。
这是我为测试各种操作而编写的程序~0:
#include <stdio.h>
int main()
{
printf("%x\n", (char)~0); // ffffffff
printf("%x\n", (unsigned char)~0); // ff
printf("%d\n", sizeof(char) == sizeof(unsigned char)); // 1
printf("%d\n", sizeof(char) == sizeof(unsigned int)); // 0
printf("%d\n", (char)~0 == (unsigned int)~0); // 1
}
Run Code Online (Sandbox Code Playgroud)
我正在努力理解为什么当char产生int- 大小的值时会unsigned char产生 -char大小的值。
0 .. v.len() - 1当向量v可能为空时,正确的循环方法是什么?
考虑以下代码,它打印向量中 2 个元素的所有选择[5, 6, 7]:
fn main() {
let v: Vec<i32> = vec![5, 6, 7];
for i in 0 .. v.len() - 1 {
for j in i + 1 .. v.len() {
println!("{} {}", v[i], v[j]);
}
}
}
Run Code Online (Sandbox Code Playgroud)
它打印
5 6
5 7
6 7
Run Code Online (Sandbox Code Playgroud)
正如预期的那样。
现在,如果我们有
let v: Vec<i32> = vec![];
Run Code Online (Sandbox Code Playgroud)
那么程序就会因为溢出而出现恐慌,这也是意料之中的。
问:如何在不改变程序结构和逻辑、不涉及有符号整数的情况下修复它?
以下是我不想要的解决方法的一些示例:
单独处理空v(改变逻辑)。总的来说,我不想要任何v空支票,例如if v.len() == 0 { 0 } …