无符号数运算

国内程序员大多上过初中数学,更习惯有符号数,但是实际上无符号数也是可以用的,只是要注意一些东西。

这里的无符号数运算指unsigned int和unsigned long long的运算,unsigned char和unsigned short会自动提升为int因此不属于无符号数运算。

0、字面量

字面量的类型默认是从int开始,最小能表示这个数的类型,比如2147483647是int,2147483648是unsigned int。

如果需要强制unsigned int,可以加U后缀,不区分大小写,比如0u0U

如果需要强制long long,可以加LL后缀,不区分大小写,比如0LL。但不推荐写成0ll,容易和011混淆。

如果需要强制unsigned long long,可以加ULL或LLU后缀,不区分大小写,比如0ull0uLL0ULL0LLu0LLU。但不推荐写成0llu0llU,容易和011u、011U混淆。

也可以使用uint32_t、int64_t、uint64_t类型和UINT32_C()、INT64_C()、UINT64_C()字面量修饰宏,比如UINT32_C(0)INT64_C(0)UINT64_C(0)

1、无符号数没有溢出,只有回卷

回卷和溢出不是一个概念,回卷是feature,溢出是bug。

无符号数运算在结果小于0或大于最大值时会按2的n次方回卷,比如

0U - 1U == 0xFFFFFFFF

0xFFFFFFFF + 1U == 0U

有符号数转换为无符号数时也会回卷,比如

(unsigned long long)-1 == 0xFFFFFFFFFFFFFFFF

有符号数与宽度相同或更宽的无符号数运算(不包括有符号数作左移/右移的移位步长),会提升为无符号数,可能导致未预期的结果,因此尽量避免不加判断地将有符号数用于含有无符号数的表达式。特别要注意的是size_t是无符号数。

2、无符号数永远大于等于0

所以for (unsigned int i = 20; i--; i >= 0)是一个死循环。

正确的应该是for (unsigned int i = 20U; i--; i != UINT_MAX)。

或者for (unsigned int i = 20U; i--; i != 0xFFFFFFFF)。

3、无符号数只有大数减小数有现实意义

小数减大数会回卷得到一个非常大的数,没有现实意义。

无符号数只能表示(没有方向的)距离而不是(有方向的)差值。

如果要表示方向的话需要再声明一个变量保存方向。

int a = 1, b = 2;
int difference = a - b;

unsigned int a = 1U, b = 2U;
unsigned int b_above_a = b > a;
unsigned int distance = max(a, b) - min(a, b);
发布了29 篇原创文章 · 获赞 1 · 访问量 3415

猜你喜欢

转载自blog.csdn.net/defrag257/article/details/102658446