前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++无符号类型数据进行运算时需要注意【隐式符号转换】

C++无符号类型数据进行运算时需要注意【隐式符号转换】

作者头像
鳄鱼儿
发布2024-07-31 09:43:46
1360
发布2024-07-31 09:43:46
举报
文章被收录于专栏:鳄鱼儿的技术分享

前言

这是一个逻辑上的疏忽,一般来讲我们常用的数都是有符号位的,稍不注意就容易出现无符号计算的漏洞。

两个有符号正数相减为负数时,当他们为无符号数时,结果应当为一个很大的无符号数。

但在运算时,小于int的无符号数可能会出现隐式符号转换(转变成有符号的数进行计算,得到结果为负数)。

以下例子中我们可以很清楚的得出以上的结论。

代码语言:javascript
复制
// 1
unsigned char a = 1;
unsigned char b = 2;

if (a - b < 0)  // a - b = -1 (signed int)
  a = 6;
else
  a = 8;

// 2
unsigned char a = 1;
unsigned short b = 2;

if (a - b < 0)  // a - b = -1 (signed int)
  a = 6;
else
  a = 8;

上述结果均为a=6

代码语言:javascript
复制
// 3
unsigned int a = 1;
unsigned short b = 2;

if (a - b < 0)  // a - b = 0xffffffff (unsigned int)
  a = 6;
else
  a = 8;
  
// 4
unsigned int a = 1;
unsigned int b = 2;

if (a - b < 0)  // a - b = 0xffffffff (unsigned int)
  a = 6;
else
  a = 8;

上述结果均为a=8

如果预期为8,则错误代码:

代码语言:javascript
复制
// Bad
unsigned short a = 1;
unsigned short b = 2;

if (a - b < 0)  // a - b = -1 (signed int)
  a = 6;
else
  a = 8;

正确代码:

代码语言:javascript
复制
// Good
unsigned short a = 1;
unsigned short b = 2;

if ((unsigned int)a - (unsigned int)b < 0)  // a - b = 0xffff (unsigned short)
  a = 6;
else
  a = 8;

避免隐式符号转换

像前面代码中所写的,在判断语句中增加无符号声明 if ((unsigned int)a - (unsigned int)b < 0),此外,我们还可以这样写:

声明另一个无符号变量 c 去约束计算式子。

代码语言:javascript
复制
// Good
unsigned short a = 1;
unsigned short b = 2;

unsigned short c = a - b; // a - b = 0xffff (unsigned short)

if (c < 0)  
  a = 6;
else
  a = 8;

在不声明新变量的情况下,我们可以直接使用 a 变量,其本身就是一个无符号变量。

代码语言:javascript
复制
// Good
unsigned short a = 1;
unsigned short b = 2;

a = a - b; // a - b = 0xffff (unsigned short)

if (a < 0)  
  a = 6;
else
  a = 8;

规避处理

对于这种预期外的结果,我们还可以通过一些处理逻辑进行规避。

比如在环形缓冲区的使用场景中,我们使用无符号整数去计算索引距离时,可以通过总缓冲区大小来说明大的无符号结果。

在进行计算时我们先判断无符号变量大小,再作判断,即可避免产生一个大的无符号数,得到期望的结果。

代码语言:javascript
复制
unsigned int buffer[256];
unsigned int head = 10;
unsigned int tail = 250;

unsigned int distance;
if (head >= tail) {
    distance = head - tail;
} else {
    distance = (256 - tail) + head;
}

总结

  • 无符号整数减法
    • 当两个无符号整数相减,结果为负数时,结果会被解释为一个很大的无符号数。
    • 例如,unsigned char a = 1; unsigned char b = 2; a - b 的结果是 0xFF(即 255),因为无符号整数不能表示负数。
  • 隐式类型转换
    • 在 C/C++ 中,算术运算符会将较小的无符号类型提升为 int 或者 unsigned int 来进行运算。这可能会导致一些意外的结果。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 避免隐式符号转换
  • 规避处理
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档