Is this standards compliant?

K

Kenny McCormack

Aka, "How to make this warning go away?"

I have some code that contains:

#define FOO 2123456789L

I.e., a number that is greater than the limit for a signed 32 bit int.

I cannot use the above in a statement w/o compiler (gcc 2.95) issuing
a warning that says: decimal constant so large it must be unsigned.

For example:

unsigned int baz = FOO;

Should be OK, right?

Notes:
1) This is on a machine where ints and longs are both 32 bits.
2) I get same results with "long" instead of "int" (in the above
declaration).

Also, I tried:

#define FOO 2000000000L+123456789L;

And I get a different error (error this time) saying integer overflow...

I assume somewhere in the standard it says that compiletime math has to
work up to some level, right?
 
B

Ben Pfaff

I have some code that contains:

#define FOO 2123456789L

I.e., a number that is greater than the limit for a signed 32 bit int.

I cannot use the above in a statement w/o compiler (gcc 2.95) issuing
a warning that says: decimal constant so large it must be unsigned.

Tell the compiler that it is unsigned:
#define FOO 2123456789UL
 
K

Kenny McCormack

Tell the compiler that it is unsigned:
#define FOO 2123456789UL

Good one. Thanks. I did not know about the U qualifier for constants.
"Your correction is 100% correct and 0% helpful. Well done!"
--Richard Heathfield

Cute. Luckily, not applicable to this thread (yet...)
 
M

Martin Ambuhl

Kenny said:
Also, I tried:

#define FOO 2000000000L+123456789L;
^^
Lose the spurious ';'. Parentheses are nice here:
#define FOO (2000000000L+123456789L)
 
O

Old Wolf

Kenny said:
Aka, "How to make this warning go away?"

I have some code that contains:

#define FOO 2123456789L

I.e., a number that is greater than the limit for a signed 32 bit
int.

The limit for a signed 32 bit int is 2147483647, so this
number is actually OK. (I guess it was some other value you
were working with..)
I assume somewhere in the standard it says that compiletime math has to
work up to some level, right?

No. Also, the math happens at run-time. Because of the as-if rule,
the compiler can do it at compile-time, but this does not necessarily
turn UB into defined behaviour.

For 16 bit int:
int a = 33000; /* UB - out of range of int (I think) */
int a = 30000 + 3000; /* UB - signed int overflow */
long a = 30000u + 3000; /* OK */
unsigned short b = 30000 + 3000; /* UB - signed int overflow */
unsigned short b = (unsigned short)30000 + 3000; /* OK */
 
K

Kenny McCormack

^^
Lose the spurious ';'.

typo (aka, transcription error).
Parentheses are nice here:
#define FOO (2000000000L+123456789L)

As someone pointed out, this isn't the actual number, so to get the desired
observed results you have to make the first digit of the second number
something greater than 1. Anyway, I tried many things with parens - none
of which helped. The trick, as someone else noted, is to put a U in there.

Thanks also to "Old Wolf" for the explanation re: the "as if" rule.
 
C

Chris Croughton

Aka, "How to make this warning go away?"

I have some code that contains:

#define FOO 2123456789L

I.e., a number that is greater than the limit for a signed 32 bit int.

I cannot use the above in a statement w/o compiler (gcc 2.95) issuing
a warning that says: decimal constant so large it must be unsigned.

If you write it with UL suffix instead of just L the warning should go
away (and you'll get a correct warning if you try to assign it to a
signed long).
For example:

unsigned int baz = FOO;

Should be OK, right?

In some languages it would, because the compiler would start at the
assignment and propagate the type to the expression (Algol and Pascal, I
believe, do that). C takes the opposite approach, it assumes that you
know what you are doing with the expression and evaluates that, then
assigns it. So the steps go something like:

evaluate 2123456789, make sure it'a a long (the L suffix). This gives
your warning.

use it to initialise baz, this works fine.
Notes:
1) This is on a machine where ints and longs are both 32 bits.
2) I get same results with "long" instead of "int" (in the above
declaration).

Yes, you would, the error is in telling the compiler that 2123456789 is
a signed long (the L suffix).
Also, I tried:

#define FOO 2000000000L+123456789L;

And I get a different error (error this time) saying integer overflow...

Also correct, you've now added two signed values and got an answer which
won't fit into a signed long.
I assume somewhere in the standard it says that compiletime math has to
work up to some level, right?

It /works/, it gave you a warning not an error. It's telling you,
though, that you may have made a mistake somewhere. For instance, you
might have 2200000000 when you meant 220000000 (the latter fitting
happily into a signed 32 bit variable). If you want the number to be
unsigned, say so explicitly by writing 2123456789UL.

Chris C
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top