整数溢出总结

1、整数提升

unsigned int Add2(unsigned short a, unsigned short b)
{
    return a + b;
}

在32位操作系统下,计算机的寄存器的位宽就是32位
在做运算时,变量 a 和 b 会分别被 push 到寄存器中
由于寄存器位宽为32,因此 变量a 与 变量b 都会被提升到为 unsigned int 类型,这就是整数提升
两个unsigned short类型的参数 相加 结果一定会在unsigned int 范围内,因此 不会有问题

  • 在表达式计算时,各种整型首先要提升到 int 类型,如果 int 类型不足以表示则要提升为 unsigned int
    类型,然后执行表达式的运算。
整型提升的意义在于:

表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度,同时也是CPU的通用寄存器的长度。因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。

2、隐式转换

unsigned short Add(unsigned short a, unsigned short b)
{
    return a + b;
}

如上述,寄存器位宽 引起 整数提升,提升后返回类型就是 unsigned int ,
而这段代码 定义 返回类型为 unsigned short ,会进行隐式转换,将 unsigned int 截断到 unsigned short

整数类型之间的转换:
  • 显式转换:通过转换语句进行的 。static_cast<新类型>
  • 隐式转换:在语句中自动发生的类型转换
发生隐式转换的场景包括:
  • 在进行算术或逻辑运算时,使其操作数隐式转换为另一个类型;
  • 函数调用时,传入的实参发生隐式转换为另一个类型,
  • 函数返回值隐式转换为另一个类型

3. 总结一:

unsigned short Add(unsigned short a, unsigned short b)
{
    return a + b;
}

// a被push到寄存器,寄存器位宽32,a和b被默认提升到32int类型        ----    整数提升:原因是操作数会进入寄存器,int会提升到uint
// 返回类型若是unsigned short,会进行隐式转换,将uint截断到ushort。----    隐式转换
unsigned int Add2(unsigned short a, unsigned short b)
{
    return a + b;
}

// a + b 还是u32类型,不会做整数提升
unsigned long Add3(unsigned int a, unsigned int b)
{
    return a + b;
    //return static_cast<unsigned long>(a) + b;
}

unsigned long long Add4(unsigned int a, unsigned int b)
{
    return a + b;
}

unsigned long long Add5(unsigned int a, unsigned int b)
{
    return static_cast<unsigned long long>(a) + b;
}

int main()
{
    cout << Add(UINT16_MAX, UINT16_MAX) << endl;  // 隐式转换 被截断

    cout << Add2(UINT16_MAX, UINT16_MAX) << endl; // 整数提升 正确输出

    cout << Add3(UINT32_MAX, UINT32_MAX) << endl; // 32位系统 long 和 int 都是32位 不论是否强转为long 都不会做整数提升

    cout << Add4(UINT32_MAX, UINT32_MAX) << endl; // 32位系统 尽管返回值类型为 long long ,不会进行整数提升

    cout << Add5(UINT32_MAX, UINT32_MAX) << endl;  // 显示强转其中一个参数,另一个参数会进行 整数提升,正确输出

    cout << sizeof(long long) << endl;

    return 0;
}

结果:
65534                           ->1111 1111 1111 1110  被截断 只取低16位bit
131070                   ->  0001 1111 1111 1111 1110  完整答案
4294967294 -> 1111 1111 1111 1111 1111 1111 1111 1110  溢出导致最后 1 bit为0 (记住无符号数:1 + 1 = 04294967294 -> 1111 1111 1111 1111 1111 1111 1111 1110  溢出导致最后 1 bit为0 (记住无符号数:1 + 1 = 08589934590
8

4. 有符号数 溢出 – 影响符号位

若算术运算的计算结果太大而无法在系统位宽范围内存储时导致整数溢出

int8: -128 - 1 = 127

二进制:1000 0000 - 1 = 0111 1111

int8:127 + 1 = -128

二进制:01111111 + 1 = 1000 0000 

5. 无符号数 反转(回绕) – 最高位进退位失效

无符号操作数的计算不会溢出,因为结果不能被无符号类型表示的时候,就会对比结果类型能表示的最大值加1再执行求模操作。

uint8:255 + 1 = 0
二进制: 1111 1111 + 1 = 0000 0000

总结二

确保无符号整数运算时不会出现反转
确保有符号整数运算时不会出现溢出
确保整型转换时不会出现截断错误
确保有符号和无符号数之间的转换符合预期
把整型表达式比较或赋值为一种更大类型之前必须用这种更大类型对他进行求值
避免对有符号整数进行位操作符运算

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Verilog中,可以通过对溢出信号进行处理来实现溢出保护。一种常见的处理方法是通过扩展存放乘累加值的寄存器的宽度来实现。对于有符号数,我们可以通过判断符号位进位异或数值最高位进位来判断是否发生了加法溢出。如果结果为1,则表示发生了溢出;反之,则没有发生溢出。 在代码实现方面,可以将溢出信号作为模块的输出之一,在模块接口定义中声明输出信号overflow。在模块内部,我们可以通过对乘累加操作的结果进行判断,将溢出信号设置为1或0来表示是否发生了溢出。这样,我们就可以在使用该模块时,通过读取溢出信号来进行溢出保护处理。 需要注意的是,为了避免在不同的always块中给同一个变量赋值,我们应该将不同逻辑的代码分成不同的代码块进行编写。这样可以避免出现综合时出现意外的逻辑错误。同时,在设计模块接口时,需要明确输入和输出信号的类型以及位宽,在代码实现中要正确使用这些信号来进行计算。 总结起来,Verilog中的溢出保护处理可以通过对溢出信号进行判断和处理来实现,具体方法包括扩展寄存器宽度、判断符号位进位异或数值最高位进位以及正确使用模块接口信号进行计算。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [溢出处理的整数乘累加器 Verilog 实现](https://blog.csdn.net/neweryyy/article/details/104627193)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值