C中关于unsigned的陷阱

引言-一个误解的诞生:

<<C++ Primer第五版>>中关于含有无符号类型的表达式的描述中有这样一句话:
当一个算数表达式中既有无符号数又有int值时,那个int值就会转换成无符号数。把int转换成无符号数的过程和把int值直接赋给无符号变量一样:

感觉Primer里的语言描述就是这样,很容易让人误解,但是当你犯错后,再回头看,又发现人也确实没讲错。

首先,我们看看这个容易让人误解的第一句话:
当一个算数表达式中既有无符号数又有int值时,那个int值就会转换成无符号数。 很多人在没有读懂第二句话的情况下理所当然就会把第一句话理解成:
如果一个算数表达式中既有无符号数又有int值,那么如果出现负数的话,会把他转换成一个无符号数的大小,再继续进行运算;em…大错特错!虽然它确实已变成了无符号类型。

我们执行一下程序:

#include <iostream>
using namespace std;
int main()
{
 unsigned int a = 5;
 int b = -1;
 cout << a + b << endl;
}

如果按照上面的思路,那应该是5+4294967292。但是程序运行后的结果却是4,咦?这不没进行转换吗?
那是不是真的没有进行转换呢?
我们再执行下以下程序:

#include <iostream>
using namespace std;
int main()
{
 unsigned int a = 1;
 int b = -5;
 cout << a + b << endl;
}

如果没有进行转换,那么结果应该是-4,但是程序运行后,结果却是:4294967292

哇!这究竟是怎么一回事?

解释

好,让我们忘掉以前的理解,重新分析Primer的两句话:

当一个算数表达式中既有无符号数又有int值时,那个int值就会转换成无符号数。
这句话其实没什么好解释的,也就是有符号类型会被类型转化成无符号类型
把int转换成无符号数的过程和把int值直接赋给无符号变量一样。
这句话才是最重要的,其意思可以理解成将有符号类型类型转化成无符号类型的过程并没有改变数的位,也就是其在内存中的二进制形式,只是改变了其看待方式(类型)

什么是看待方式?
我们分析下不同的看待方法,会有什么样的不同:
比如二进制数:1111,1111,1111,1111
对于int: 它是补码,表示 -1
对于unsigned int: 它是 4294967292
也就是说同一个二进制数,不同的类型,其表示的值是不同的。

但是我们进行运算时,机器用的仍然是用的二进制数。也就是说机器运算时有符号数与无符号数的运算并没有什么区别,而不能以-1变成了4294967292来看待。

总结
所以我们大可以不必区分一个计算式中是有符号还是无符号数,其实他们的机器运算是完全一样的。只不过我们对于它的运算结果-这个二进制数需要以不同的方式来看待它。当结果是正数时,也没有区别,但当其为负数,我们需要把他当成无符号数再看待。

备注:
返回值类型为size_t,其本质是unsigned int,所以需要特别注意!比如sizeof(),strlen()等。

发布了8 篇原创文章 · 获赞 22 · 访问量 3316

猜你喜欢

转载自blog.csdn.net/weixin_43406295/article/details/102707254