整数减法问题,求助! [英] Integer subtraction problem, help!

查看:84
本文介绍了整数减法问题,求助!的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



i在C中有整数减法问题。


printf("%d",c<(a - b)) ;


a来自#define,是0x80000000,b来自输入,

也是0x80000000。

c是ffffffff(-1)。

现在,这应该打印1(真)但它打印0!


如果我将其修改为

d = a - b;

printf("%d",c< d);

它正确打印1。

我很难过,请帮忙!我想在

比较中发生了一些错误,我不知道是什么。

如果我只保留我的第二种方法,那么一切正常吗?或者是

有一些风险吗?


非常感谢

布鲁斯

hi
i have a problem with integer subtraction in C.

printf("%d", c < (a - b));

a is got from a #define and is 0x80000000 and b is got from input and
is also 0x80000000.
c is ffffffff (-1).
Now, this should print 1 (true) but it prints 0!

If I modify this to
d = a - b;
printf("%d", c < d);
it prints 1 correctly.

I am stumped, please help! i guess something wrong happens during the
comparison, i dont know what.
If i just retain my second method which works, is everything ok? or is
there some risk?

thanks a lot
bruce

推荐答案

在文章< 11 ********************* @ l41g2000cwc.googlegroups中。 com>,
br ************* @ gmail .com 写道:
In article <11*********************@l41g2000cwc.googlegroups. com>,
br*************@gmail.com wrote:

我在C中有整数减法问题。

printf("%d" ,c<(a - b));

a来自#define,是0x80000000,b来自输入,
也是0x80000000。
c是ffffffff(-1)。
hi
i have a problem with integer subtraction in C.

printf("%d", c < (a - b));

a is got from a #define and is 0x80000000 and b is got from input and
is also 0x80000000.
c is ffffffff (-1).




如果你的意思是0xffffffff,那肯定和-1不一样。


Take一本关于C的好书,并查看_exactly_各种

操作数的类型。



If you mean 0xffffffff, that is definitely not the same as -1.

Take a good book about C and check out _exactly_ what types the various
operands have.


来自: br ************* @ gmail.com


在两篇不同的文章中,

< 11 ********************** @ f14g2000cwb.googlegroups .com>



< 11 ********************* @ l41g2000cwc.googlegroups。 com>

< br ************* @ gmail.com>写道:
From: br*************@gmail.com

In two different articles,
<11**********************@f14g2000cwb.googlegroups .com>
and
<11*********************@l41g2000cwc.googlegroups. com>
<br*************@gmail.com> wrote:
我在C中有整数减法问题。
printf("%d",c<(a - b));
a是从#define获得的,是0x80000000,b是从输入获得的,
也是0x80000000。
c是ffffffff(-1)。
现在,这应该打印1(true)但它打印0!

如果我修改为


[这里是两篇文章不同的地方]

d = c< ; (a - b);
printf("%d",d);
它正确打印1。


这意味着编译器错误。

d = a - b;
printf("%d",c< d);
它正确打印1。


这完全意味着别的东西。

我很难过,请帮忙!我想在
比较期间发生了一些错误,我不知道是什么。
i have a problem with integer subtraction in C.
printf("%d", c < (a - b));
a is got from a #define and is 0x80000000 and b is got from input and
is also 0x80000000.
c is ffffffff (-1).
Now, this should print 1 (true) but it prints 0!

If I modify this to
[here is where the two articles differ]
d = c < (a - b);
printf("%d", d);
it prints 1 correctly.
This would imply a compiler bug.
d = a - b;
printf("%d", c < d);
it prints 1 correctly.
This would imply something else entirely.
I am stumped, please help! i guess something wrong happens during the
comparison, i dont know what.




这里的情况有点像开车进店的人

有问题。机修工看着车:我什么都没看到

这里错了。 哦,*这个*不是有问题的车。我驾驶这辆车是因为另一个人不会开始!


大概有些东西*是*错的,但是你还没有带来

实际代码,只是它的一些小片段。 (在上面的比喻中,这个家伙可能从有故障的汽车上带来了点烟器。:-))但是,你可以猜到你的完整

计划:


%cat tc

#include< stdio.h>


#define a 0x80000000

int main(void){

int b = 0x80000000,c = 0xffffffff,d;


printf(" c<(a-b):%d \ n",c<(a-b)); / *第8行* /

d = a - b;

printf(" c< d:%d \ n",c< d);

返回0;

}

%cc -ansi -pedantic -ot tc

%。/ t

c< (a-b):0

c< d:1




这与你描述的症状相同

< news:11 ***** ****************@l41g2000cwc.googlegr oups.com> ;.

注意如果我们问编译器会发生什么(GNU的GCC,在此case)

formaximal warnings:


%cc -O -Wall -W -ansi -pedantic -ot tc

tc:在函数`main'':

tc:8:警告:签名和未签名之间的比较




(第8行是注释的printf()调用)。这是你的理由

出了什么问题。


在32位 - int上系统就像我在这里使用的那样,常量

0x80000000的类型为unsigned int。表达式:


c< (0x80000000-b)


有三个操作数:一个int (c),一个unsigned int (0x80000000),

和另外一个int (b)中。带括号的子表达式首先被分组为
,并且C编译器必须找到用于

结果的类型基于除了两者的类型之外的任何其他类型的减法操作数。

因为一个是unsigned int另一个是普通(签名)int,

计算将使用无符号算术完成,产生一个

unsigned int结果。 b中的值首先转换为unsigned

int,再次给出0x80000000U,结果是unsigned int 0,

所以这意味着:


c< 0U


变量c当然是-1,但是这个表达式通过将c转换为unsigned int来进行

比较,产生UINT_MAX或

(关于此实现)4294967295,所以这意味着:


4294967295U< 0美元


当然不是。


通过将减法的结果赋值给d - 一个普通的

签名int - 我们得到第二个比较比较-1和0(两个

普通签名" int" s),当然 - 1小于0.


请注意,这里一个更基本的问题是你已经定义了

a作为0x80000000,这是数字2147483648,但是在你的
机器上(以及我用来编译上面的测试用例的机器),INT_MAX

是2147483647.当你发生什么事情把2147483648放入一个变量

,它不能容纳大于2147483647的数字?几乎就像你把10加仑的水加到5加仑的b $ b桶中一样:它溢出了。为了扩展这个类比,C不会指示地板是木头(经线)还是瓷砖(这是一个防水且不会变形的b
$ b)在这一点上是你自己的。

如果你想让语言本身指定结果,避免这种

类溢出。如果你觉得安全,取决于总是有

瓷砖地板因为它是 - 也就是说,如果你确定你将永远使用你现在使用的机器
,你可以依赖任何

额外的保证。在comp.lang.c新闻组,

thuogh,我们通常会尽量阻止这种取决于机器的价值,至少在可能的情况下;我们尽量不要谈论任何一台机器的具体细节,因为C运行在

这么多不同行为的机器上。

-

In-Real-Life:风河系统Chris Torek

美国犹他州盐湖城(40°39.22''N,111°50.29 ''W)+1 801 277 2603

电子邮件:忘了它 http://web.torek.net/torek/index.html

由于垃圾邮件发送者,阅读电子邮件就像在垃圾中搜索食物一样。



The situation here is a bit like a guy who drives into an auto shop
with a problem. The mechanic looks at the car: "I don''t see anything
wrong here." "Oh, *this* isn''t the car with the problem. I drove
this one in because the other one won''t start!"

Presumably something *is* wrong, but you have not brought in the
actual code, just some little snippet from it. (In the analogy
above, the guy might have brought in the cigarette lighter from
the faulty car. :-) ) Still, one can make a guess at your complete
program:

% cat t.c
#include <stdio.h>

#define a 0x80000000

int main(void) {
int b = 0x80000000, c = 0xffffffff, d;

printf("c < (a - b): %d\n", c < (a - b)); /* line 8 */
d = a - b;
printf("c < d: %d\n", c < d);
return 0;
}
% cc -ansi -pedantic -o t t.c
% ./t
c < (a - b): 0
c < d: 1
%

This has the same symptoms you describe in
<news:11*********************@l41g2000cwc.googlegr oups.com>.
Note what happens if we ask the compiler (GNU''s GCC, in this case)
for "maximal warnings":

% cc -O -Wall -W -ansi -pedantic -o t t.c
t.c: In function `main'':
t.c:8: warning: comparison between signed and unsigned
%

(line 8 is the commented printf() call). This is your clue as to
what is wrong.

On a 32-bit-"int" system like the one I used here, the constant
0x80000000 has type "unsigned int". The expression:

c < (0x80000000 - b)

has three operands: one "int" (c), one "unsigned int" (0x80000000),
and one more "int" (b). The parenthesized sub-expression is grouped
first, and a C compiler must find the type to use for the result of
the subtraction based on nothing but the types of the two operands.
Since one is "unsigned int" and the other is plain (signed) "int",
the computation will be done with unsigned arithmetic, producing an
unsigned int result. The value in b is first converted to unsigned
int, giving 0x80000000U again, and the result is the unsigned int 0,
so this means:

c < 0U

The variable c is of course -1, but this expression does the
comparison by converting c to unsigned int, producing UINT_MAX or
(on this implementation) 4294967295, so this means:

4294967295U < 0U

and of course it is not.

By assigning the result of the subtraction to "d" -- an ordinary
signed int -- we get the second comparison to compare -1 and 0 (two
ordinary signed "int"s), and of course -1 is less than 0.

Note that a more fundamental problem here is that you have defined
"a" as 0x80000000, which is numerically 2147483648, but on your
machine (and the one I used to compile the test case above), INT_MAX
is 2147483647. What happens when you put 2147483648 into a variable
that cannot hold a number bigger than 2147483647? Pretty much the
same thing as when you put ten gallons of water into a five-gallon
bucket: it overflows. To extend this analogy a bit, C does not
specify whether the floor is wood (which warps) or tile (which is
waterproof and does not warp) -- you are on your own at this point.
If you want the language itself to specify the result, avoid this
kind of overflow. If you feel safe in depending on "always having
tile floors" as it were -- that is, if you are sure you will always
use the machine you are using right now -- you can depend on any
additional guarantees it makes. Here in the comp.lang.c newsgroup,
thuogh, we generally try to discourage this kind of "depending on
the machine", at least whenever possible; and we try not to talk
too much about the specifics of any one machine, since C runs on
so many different machines with different behaviors.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22''N, 111°50.29''W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.


br *********** **@gmail.com 写道:
我在C中有整数减法问题。

printf("%d",c<( a - b));

a来自#define并且是0x80000000
而b来自输入,也是0x80000000。
c是ffffffff(-1) 。
现在,这应该打印1(真实),但它打印s 0!

如果我将其修改为
d = a - b;
printf("%d",c< d);
它正确打印1。
i have a problem with integer subtraction in C.

printf("%d", c < (a - b));

a is got from a #define and is 0x80000000
and b is got from input and is also 0x80000000.
c is ffffffff (-1).
Now, this should print 1 (true) but it prints 0!

If I modify this to
d = a - b;
printf("%d", c < d);
it prints 1 correctly.




你没有发布确切的代码,所以我要做一些假设:

- 你在32位整数的机器上

- ''b''是无符号整数(一个有符号的int不能容纳0x80000000)

- ''c''是一个签名的int,它包含-1(不是ffffffff)

- ''''是一个签名的int;


现在,0x80000000(十进制,2147483648)太大而无法在有符号的int中使用
,因此编译器将其视为unsigned int。

所以(a-b)的类型为unsigned int。价值为0.


所以我们已经将问题减少到签署的旧C''缺陷' -
无符号比较。如果你写了

,你会得到相同的结果:

printf("%d",-1< 0u);


在C中,二元运算符(即采用2个操作数的运算符)

必须具有相同类型的两个操作数。你赋予它不同的

类型(一个是signed int,另一个是unsigned int)。编译器

''通过将signed int转换为unsigned来解决'这个问题,

因此它最终进行比较4294967295< 0,如你看到的那样,
结果是假的。


在'd'的情况下,你比较两个整数,所以

没有发生转换,-1< 0当然是真的。


在您的具体示例中,您可以解决以下问题:

printf("%d \ n",c <(int)(a - b));


但是如果(a - b)没有保持有效的int值(例如,如果a是
$ b) $ b 0x80000000和b是0),那么你有未定义的行为。

所以一般来说,如果你需要比较全部范围的

签名的整数范围无符号整数,你会想要这样的函数:


int less_than(int a,unsigned int b)

{

if(b> INT_MAX)返回0;

返回< (int)b;

}



You didn''t post exact code, so I''m going to make some assumptions:
- You''re on a machine with 32-bit ints
- ''b'' is an unsigned int (A signed int can''t hold 0x80000000)
- ''c'' is a signed int which holds -1 (not ffffffff)
- ''d'' is a signed int;

Now, 0x80000000 (in decimal, 2147483648) is too big to fit
in a signed int, so the compiler treats it as an unsigned int.
So (a - b) has type "unsigned int" and value 0.

So we have reduced the problem to the old C ''flaw'' of signed-
unsigned comparisons. You would get the same result if
you wrote:
printf("%d", -1 < 0u);

In C, binary operators (that is, operators that take 2 operands)
must have both operands the same type. You gave it different
types (one is signed int, the other unsigned int). The compiler
''solves'' this problem by converting the signed int to unsigned,
so it ends up doing the comparison 4294967295 < 0 , which
turns out to be false as you have seen.

In your case with ''d'', you are comparing two ints, so
no conversions occur, and -1 < 0 is of course true.

In your specific example you can fix the problem like this:
printf("%d\n", c < (int)(a - b));

But if (a - b) did not hold a valid int value (eg. if a is
0x80000000 and b is 0), then you have undefined behaviour.
So in general, if you need to compare the full range of
signed ints with the full range of unsigned ints, you would
need a function like this:

int less_than(int a, unsigned int b)
{
if (b > INT_MAX) return 0;
return a < (int)b;
}


这篇关于整数减法问题,求助!的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆