这是非常简单的代码,无符号和符号比较
#include <iostream>
using namespace std;
int main() {
unsigned int u=10;
int i;
int count=0;
for (i=-1;i<=u;i++){
count++;
}
cout<<count<<"\n";
return 0;
}
计数的值是0,为什么?
这是非常简单的代码,无符号和符号比较
#include <iostream>
using namespace std;
int main() {
unsigned int u=10;
int i;
int count=0;
for (i=-1;i<=u;i++){
count++;
}
cout<<count<<"\n";
return 0;
}
计数的值是0,为什么?
的<=
两个操作数必须被提升到相同的类型。
很明显,他们被提升为unsigned int
(我没有来自我面前的标准的规则,我会在一秒钟内看到它)。由于(unsigned int)(-1) <= u
为假,所以循环从不执行。
的规则标准,第10段,其中指出(我已经强调了在这里也适用该规则)第5条(表达式)发现:
许多双目操作符,预计算术操作数或枚举类型以相似的方式导致转换和产生结果类型。目的是产生一个共同的类型,这也是结果的类型。 这种模式如下被称为通常的算术转换,其被定义为:
- 如果一个操作数的范围的枚举类型(7.2)的,不会进行任何转换;如果另一个操作数不具有相同的类型,则该表达式不合格。
- 如果任一操作数的类型为long double,则另一个操作数应转换为long double。
- 否则,如果其中一个操作数为双倍,另一个应转换为双倍。
- 否则,如果任一操作数是浮点数,则另一个操作数应转换为浮点数。
- 否则,积分促销(4.5)应在两个操作数上执行。 60然后,下面的 规则应用于提升的操作数:
- 如果两个操作数具有相同类型,则不需要进一步转换。否则,如果两个操作数具有带符号整数类型或两者都具有无符号整数类型,则具有较小整数转换等级类型的操作数应转换为具有较高等级的操作数的类型。
- 否则,如果具有无符号整数类型的操作数的秩大于或等于另一操作数类型的秩,则带符号整数类型的操作数应转换为无符号整数类型的操作数的类型。
- 否则,如果具有有符号整数类型的操作数的类型可以表示具有无符号整数类型的操作数类型的所有值,则具有无符号整数类型的操作数应转换为带有符号的操作数的类型整数类型。
- 否则,两个操作数都应转换为与带符号整数类型的操作数的类型相对应的无符号整数类型。
它因为-1是作为unsigned int输出的,所以for循环代码永远不会执行。
尝试用-Wall编译-Wextra这样你就可以得到相应的警告(如果不是让他们到目前为止,并与G ++编译)
谢谢,我想问你一件事我会给我的问题的链接,请告诉我为什么他们减少我的标记或他们downvote好吗?我想拥有良好的声誉并试图发布很好的问题,但他们会减少它 – 2010-08-02 04:08:45
@davit:你的其他问题因为编译器告诉你到底发生了什么错误(你错过了一个分号),但是你在这里没有发布你的问题试图自己解决问题。 – 2010-08-02 04:20:55
在比较过程中(i <= u)
,i
升级为一个无符号的整数,并在此过程中-1转换为UINT_MAX。
负数的,以一个unsigned int将增加(UINT_MAX + 1)到数模转换,所以-1变成UINT_MAX,-2变为UINT_MAX - 1等
如果你想想看,必须将一个转换为另一个才能进行比较才能正常工作,并且通常编译器会将有符号值转换为无符号值。在这种情况下,当然,将无符号值转换为带符号的值会更有意义,但编译器不能只根据您的意图来决定遵循不同的规范。你应该在这里明确地将unsigned int转换为signed(或者只是将它作为一直签名)。
你的规则不起作用。实际上,2 ** 32被添加,即'UINT_MAX + 1',而不是'UINT_MAX - 1'。 – 2010-08-02 04:16:13
感谢Ben,我已经改正了 - 现在改为+。 – thomasrutter 2010-08-02 04:20:13
WRT你的新评论,从signed到unsigned的转换对于所有输入都是明确定义的,但是从unsigned到signed的转换可以调用实现定义的行为(这里不会,因为u的值是10适合'int')。 – 2010-08-02 04:25:49
在一个整数以4个字节存储的系统中,我认为-1的值等于2147483649(1000 0000 0000 0000 0000 0000 0000 0001)的值 - 它是1,MSB设置为1来指示这是消极的。
不,在二进制补码表示中,'-1'被存储为全1。但实际的表示并不重要,因为C++标准定义了从符号到无符号整数类型的转换,在模块的基本N运算中全等。 – 2010-08-02 04:18:18
虽然在符号量级系统中这是事实,但现在这些情况非常罕见。大多数合理的当前系统使用2的补码来表示整数,在这种情况下,-1将被设置为1的所有位表示(在这种情况下,从有符号到无符号的转换完全不需要改变数据,只改变它的方式解释)。 – 2010-08-02 04:20:45
@Jerry:符号的数量并不少见。 IEEE 754要求它。几乎每台计算机都使用二进制补码整数和符号量级浮点表示。 – 2010-08-02 04:33:41
这是因为i
在比较之前被提升为无符号值。这会将其设置为值为UINT_MAX
,在32位计算机上的值等于4294967295
。所以,你的循环本质上是一样的:
// will never run
for (i = 4294967295; i <= u; i++) {
count++;
}
顺便说一句,你应该使用'的std :: endl'而不是插入'\ N'成流,因为'的std :: endl'两者是便携式的,确保输出立即显示。 – 2010-08-02 04:57:40
@本:'\ n'就像便携式;如果您现在特别想要刷新流,则只应使用'endl'。 – 2010-08-02 10:55:22
'\ n'是可移植的(它被转换为平台的换行顺序),并且不会立即刷新流的开销。你应该使用具有你想要的语义的那个:如果你想让流被刷新,使用'endl',如果你只想换行,可以使用'\ n'。 – jalf 2010-09-27 23:06:18