Hi,
I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits
and long long ints are 64 bits.
When i have:
int num=9600;
long long int reg=(long long)8000000000 00/(5000000*num);
the denominator overflows and gives an incorrect answer: reg=1059
With an extra cast:
long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
i get: reg=16
If the numerator is a long long int, should the denominator be
automatically promoted to a long long int? 20 2356
Russell Shaw wrote: Hi, I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits and long long ints are 64 bits.
When i have:
int num=9600; long long int reg=(long long)8000000000 00/(5000000*num);
the denominator overflows and gives an incorrect answer: reg=1059
With an extra cast:
long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
i get: reg=16
If the numerator is a long long int, should the denominator be automatically promoted to a long long int?
lcc-win32 gives the same answer as gcc. The problem is
that the denomitar *is* converted to long long. The
compiler does:
long long int reg=(long long)8000000000 00/(long long)(5000000*n um);
Neither gcc nor lcc-win32 realize that the denominator is an
expression, converting each member to the highest rank type.
Maybe there are compilers that clever, but I would not rely
on it, and would add the cast.
jacob
Russell Shaw wrote: Hi, I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits and long long ints are 64 bits.
When i have:
int num=9600; long long int reg=(long long)8000000000 00/(5000000*num);
the denominator overflows and gives an incorrect answer: reg=1059
With an extra cast:
long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
i get: reg=16
If the numerator is a long long int, should the denominator be automatically promoted to a long long int?
Yes. But the denominator (in the first form) is itself
the product of two factors of type `int', so it is calculated
in `int' arithmetic. The product is too large for an `int',
so it overflows and is chopped down to 32 bits (on your system;
C itself doesn't guarantee what happens). Then the already-
damaged value is promoted to `long long' for the division, but
it's too late: the denominator is much smaller than intended,
so the quotient comes out much too large.
In the second form, the 5000000 term is converted to `long
long' by the cast operator. The denominator is then the product
of a `long long' and an `int', so `num' is converted to `long
long' and the multiplication is carried out in `long long'
arithmetic and does not overflow. Then the division takes
place, and everything comes out as expected.
A better way to write this would be to make the constants
`long long' to begin with:
long long int reg = 800000000000LL / (5000000LL * num);
--
Eric Sosman es*****@acm-dot-org.invalid
On Sun, 02 Jan 2005 17:26:27 +0100, jacob navia
<ja***@jacob.re mcomp.fr> wrote: lcc-win32 gives the same answer as gcc. The problem is that the denomitar *is* converted to long long. The compiler does:
long long int reg=(long long)8000000000 00/(long long)(5000000*n um);
Neither gcc nor lcc-win32 realize that the denominator is an expression, converting each member to the highest rank type.
Nor should they, C is specified such that conversions occur only when
they are forced because the types are dissimilar (or when forced with a
cast). For instance:
long long denom = 5000000 * num;
will give the same overflow, because it is specified that 5000000*num is
calculated and only then converted to a long long.
Maybe there are compilers that clever, but I would not rely on it, and would add the cast.
It would not be 'clever', it would be against the standard. There are
other /languages/ which have the semantics the other way round, so that
expression type is propagated left to right (Algol and Pascal, I
believe, do that), but any C compiler must do the sub-expressions first
and promote the types only when it is necessary because the other
operand is a higher type.
Chris C
Russell Shaw <rjshawN_o@s_pa m.netspace.net. au> writes: I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits and long long ints are 64 bits.
When i have:
int num=9600; long long int reg=(long long)8000000000 00/(5000000*num);
the denominator overflows and gives an incorrect answer: reg=1059
With an extra cast:
long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
i get: reg=16
If the numerator is a long long int, should the denominator be automatically promoted to a long long int?
The evaluation of an expression is not affected by the context in
which it appears. Think of expressions, including their
subexpressions, as being evaluated bottom-up, not top-down.
The right operand of the "/" operator is:
(5000000*num)
Each operand of the "*" is of type int, so it's an int-by-int
multiplication yielding an int result. (It overflows, which invokes
undefined behavior, which most likely shows up as discarding the
high-order bits.) That int result then becomes the right operand of
the "/" operator. The left operand of the "/" operator is (long
long)8000000000 00, which is of type long long, so the right operand is
promoted to long long -- but that promotion (to 64 bits) is done
*after* the 32-bit multiplication.
Since the overflow invokes undefined behavior, I suppose a
sufficiently clever compiler could let the context affect the
evaluation of (5000000*num), so the whole expression yields a
mathematically correct result. But such cleverness doesn't really do
you any favors, it merely masks your error.
(There are languages in which the context of an expression affects its
evaluation. C is not such a language.)
You might prefer to use a suffix on the integer constants rather than
casting them to long long:
long long int reg=80000000000 0LL/(5000000LL*num) ;
On the other hand, the cast uses the type name explicitly, so it might
be considered clearer.
--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Chris Croughton <ch***@keristor .net> writes: On Sun, 02 Jan 2005 17:26:27 +0100, jacob navia <ja***@jacob.re mcomp.fr> wrote:
[...] Maybe there are compilers that clever, but I would not rely on it, and would add the cast.
It would not be 'clever', it would be against the standard.
[...]
As I mentioned in another thread, it wouldn't be against the standard
if it affected the visible behavior of the program only when it
invokes undefined behavior. But such "cleverness " would not be a good
idea, since it would tend to mask errors.
--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Keith Thompson <ks***@mib.or g> writes: Chris Croughton <ch***@keristor .net> writes: On Sun, 02 Jan 2005 17:26:27 +0100, jacob navia <ja***@jacob.re mcomp.fr> wrote: [...] Maybe there are compilers that clever, but I would not rely on it, and would add the cast.
It would not be 'clever', it would be against the standard.
[...]
As I mentioned in another thread, it wouldn't be against the standard if it affected the visible behavior of the program only when it invokes undefined behavior. But such "cleverness " would not be a good idea, since it would tend to mask errors.
Sorry, I meant to say "As I mentioned elsewhere in this thread ...".
--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
On Sun, 02 Jan 2005 23:03:44 GMT, Keith Thompson <ks***@mib.or g> wrote
in comp.lang.c: Chris Croughton <ch***@keristor .net> writes: On Sun, 02 Jan 2005 17:26:27 +0100, jacob navia <ja***@jacob.re mcomp.fr> wrote: [...] Maybe there are compilers that clever, but I would not rely on it, and would add the cast.
It would not be 'clever', it would be against the standard.
[...]
As I mentioned in another thread, it wouldn't be against the standard if it affected the visible behavior of the program only when it invokes undefined behavior. But such "cleverness " would not be a good idea, since it would tend to mask errors.
True. But if either of the operands in the calculation of the
denominator were unsigned, such 'early promotion' would be
non-conforming.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.l earn.c-c++ http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
"Keith Thompson" <ks***@mib.or g> wrote in message
news:ln******** ****@nuthaus.mi b.org... Russell Shaw <rjshawN_o@s_pa m.netspace.net. au> writes: I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits and long long ints are 64 bits.
When i have:
int num=9600; long long int reg=(long long)8000000000 00/(5000000*num);
the denominator overflows and gives an incorrect answer: reg=1059
With an extra cast:
long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
i get: reg=16
If the numerator is a long long int, should the denominator be automatically promoted to a long long int? The evaluation of an expression is not affected by the context in which it appears. Think of expressions, including their subexpressions, as being evaluated bottom-up, not top-down.
The right operand of the "/" operator is:
(5000000*num)
Each operand of the "*" is of type int, so it's an int-by-int multiplication yielding an int result. (It overflows, which invokes undefined behavior, which most likely shows up as discarding the high-order bits.) That int result then becomes the right operand of the "/" operator. The left operand of the "/" operator is (long long)8000000000 00, which is of type long long, so the right operand is promoted to long long -- but that promotion (to 64 bits) is done *after* the 32-bit multiplication.
Since the overflow invokes undefined behavior, I suppose a sufficiently clever compiler could let the context affect the evaluation of (5000000*num), so the whole expression yields a mathematically correct result. But such cleverness doesn't really do you any favors, it merely masks your error.
(There are languages in which the context of an expression affects its evaluation. C is not such a language.)
You might prefer to use a suffix on the integer constants rather than casting them to long long:
long long int reg=80000000000 0LL/(5000000LL*num) ;
Hi Keith,
I used the following form :
int num = 9600;
long long int i = (long long)8000000000 00/(5000000LL * num);
printf("%ld\n", i);
on my Win XP machine (gcc 3.3.1) gcc flash out the following warning :
longlong.c: In function `main':
longlong.c:7: warning: integer constant is too large for "long" type
output : 16
and to more surprise when compiling the same code on Solaris Workstation
with gcc 3.3 warning was the same as above but the result :
output : 0
WHY IT IS SO??????
Thanks n Regards
-Neo On the other hand, the cast uses the type name explicitly, so it might be considered clearer.
-- Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst> San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst> We must do something. This is something. Therefore, we must do this.
Neo wrote: "Keith Thompson" <ks***@mib.or g> wrote in message news:ln******** ****@nuthaus.mi b.org...
Russell Shaw <rjshawN_o@s_pa m.netspace.net. au> writes:
I'm using gcc-3.4.3 on a linux pc. The ints and long ints are 32 bits and long long ints are 64 bits.
When i have:
int num=9600; long long int reg=(long long)8000000000 00/(5000000*num);
the denominator overflows and gives an incorrect answer: reg=1059
With an extra cast:
long long int reg=(long long)8000000000 00/((long long)5000000*nu m);
i get: reg=16
If the numerator is a long long int, should the denominator be automaticall y promoted to a long long int?
The evaluation of an expression is not affected by the context in which it appears. Think of expressions, including their subexpression s, as being evaluated bottom-up, not top-down.
The right operand of the "/" operator is:
(5000000*num)
Each operand of the "*" is of type int, so it's an int-by-int multiplicatio n yielding an int result. (It overflows, which invokes undefined behavior, which most likely shows up as discarding the high-order bits.) That int result then becomes the right operand of the "/" operator. The left operand of the "/" operator is (long long)80000000 0000, which is of type long long, so the right operand is promoted to long long -- but that promotion (to 64 bits) is done *after* the 32-bit multiplication.
Since the overflow invokes undefined behavior, I suppose a sufficientl y clever compiler could let the context affect the evaluation of (5000000*num), so the whole expression yields a mathematicall y correct result. But such cleverness doesn't really do you any favors, it merely masks your error.
(There are languages in which the context of an expression affects its evaluation. C is not such a language.)
You might prefer to use a suffix on the integer constants rather than casting them to long long:
long long int reg=80000000000 0LL/(5000000LL*num) ;
Hi Keith,
I used the following form :
int num = 9600; long long int i = (long long)8000000000 00/(5000000LL * num); printf("%ld\n", i);
on my Win XP machine (gcc 3.3.1) gcc flash out the following warning : longlong.c: In function `main': longlong.c:7: warning: integer constant is too large for "long" type output : 16
and to more surprise when compiling the same code on Solaris Workstation with gcc 3.3 warning was the same as above but the result : output : 0
WHY IT IS SO??????
RTFmanpage (printf):
The length modifier l specifies _long_, not _long_long_.
If you want to print a long long, use ll:
printf("%lld\n" , i);
Depending on the byte representation of the number in memory, we may
well arrive at 16 (korrekt) or 0, if erroneously reading only a part
of the bytes belonging to the argument.
Cheers
Michael
--
E-Mail: Mine is a gmx dot de address. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Carsten Hansen |
last post by:
Suppose I'm using an implementation where an int is 16 bits.
In the program below, what function is called in the first case,
and what is called in the second case?
Also, if there is a difference between C89 and C99, I would
like to know.
I have tried with different compilers, and I see some differences.
Before I file a bug report with my C vendor, I would like to
know what the correct behavior is.
struct S
|
by: TTroy |
last post by:
Hello, I'm relatively new to C and have gone through more than 4 books
on it. None mentioned anything about integral promotion, arithmetic
conversion, value preserving and unsigned preserving. And K&R2
mentions "signed extension" everywhere.
Reading some old clc posts, I've beginning to realize that these books
are over-generalizing the topic. I am just wondering what the
difference between the following pairs of terms are:
1)...
|
by: shmartonak |
last post by:
I have the following program. Under linux I've compiled it with gcc and in DOS
I've compiled it with TURBOC 2.01. I get different outputs when I run it.
/* start of program */
#include <stdio.h>
int main()
{
unsigned char u1=200, u2=200;
unsigned long l1 = 0;
|
by: Frederick Gotham |
last post by:
I set about trying to find a portable way to set the value of UCHAR_MAX. At
first, I thought the following would work:
#define UCHAR_MAX ~( (unsigned char)0 )
However, it didn't work for me. Could someone please explain to me what's
going on? I would have thought that the following happens:
(1) The literal, 0, whose type is int, gets converted to an unsigned char.
|
by: spibou |
last post by:
On 6.3.1.1 of N1124 we read:
If an int can represent all values of the
original type, the value is converted to
an int; otherwise, it is converted to an
unsigned int.
A few lines above that we read:
The following may be used in an expres-
| |
by: sarathy |
last post by:
Hi,
What is integer promotion? How is it different from
arithmetic conversion?
Regards,
Sarathy
|
by: charles_gero |
last post by:
Hi all,
I had a question about the topics in the subject and posted to
comp.std.c, but feel it may also be appropriate here. Please excuse
this crosspost if it is in bad form.
I have a question about whether or not I am interpreting a nuance of
the standard correctly, and the implications of said nuance. The
sections in the C99 standard (and possibly older standards) that I will
reference are as follows (typed out hopefully to avoid...
|
by: Sune |
last post by:
Hi all,
there are several situations where integer promotion is performed in C
and I need to confirm my understanding of it. Let's contain the
discussion to workstation/server CPUs of 32/64 bits, I'm afraid 8/16
bits CPUs may add details I'm not interested in. Hopefully someone
here can help out:
- As long as I use function prototypes there will be no argument
integer promotions (unless they are variadic)
|
by: thomas.mertes |
last post by:
Is it possible to use some C or compiler extension to catch
integer overflow?
The situation is as follows:
I use C as target language for compiled Seed7 programs.
For integer computions the C type 'long' is used.
That way native C speed can be reached.
Now I want to experiment with raising a Seed7 exception
(which is emulated with setjmp(), longjmp() in C) for integer
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
| |
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own....
Now, this would greatly impact the work of software developers. The idea...
|
by: isladogs |
last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM).
In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules.
He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms.
Adolph will...
|
by: conductexam |
last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one.
At the time of converting from word file to html my equations which are in the word document file was convert into image.
Globals.ThisAddIn.Application.ActiveDocument.Select();...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: 6302768590 |
last post by:
Hai team
i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |