defining constant for use as an int

Started by WobberJ May 7, 2005
Hi all,
For this question, I'm using the IAR 3.10a
evaluation kit, with a MC9S12C32 chip.

This may be a basic C question, but here goes...

I've got a function that takes an int argurment:

void sciInit (int baud);

I'm calling it with a constant that is defined
in a macro:

sciInit (BAUD_9600);

My problem is:

this definition of BAUD_9600 works:

#define BAUD_9600 (40000 / (16 * 96));

This definition is the human readable form, but gives a
compile warning (and doesn't work):

#define BAUD_9600 (4000000 / (16 * 9600));

The warning is:
Warning[Pe061]: integer operation result is out of range

My question is:
Why does the compiler care? shouldn't the pre-processor
evaluate the constant expression _before_ the data type
is determined to be insufficient to hold the result?

TIA,
JoeW



In a message dated 5/7/05 1:39:30 P.M. Eastern Daylight Time,
wobberj@wobb... writes:

#define BAUD_9600 (4000000 / (16 * 9600));

The warning is:
Warning[Pe061]: integer operation result is out of range

My question is:
Why does the compiler care? shouldn't the pre-processor
evaluate the constant expression _before_ the data type
is determined to be insufficient to hold the result?

==========================
Maybe the preprocesser evals all expressions as int?


Hi,
I found that the following cast works:

#define BAUD_9600 (4000000 / ((long) 16 * 9600));

It was the multiply that was overflowing and giving the warning.
Thanks,
JoeW

--- In 68HC12@68HC..., BobGardner@a... wrote:
>
> In a message dated 5/7/05 1:39:30 P.M. Eastern Daylight Time,
> wobberj@y... writes:
>
> #define BAUD_9600 (4000000 / (16 * 9600));
>
> The warning is:
> Warning[Pe061]: integer operation result is out of range
>
> My question is:
> Why does the compiler care? shouldn't the pre-processor
> evaluate the constant expression _before_ the data type
> is determined to be insufficient to hold the result? >
>
> ==========================
> Maybe the preprocesser evals all expressions as int? >


At 08:10 PM 05/07/2005, you wrote:

>Hi,
>I found that the following cast works:
>
>#define BAUD_9600 (4000000 / ((long) 16 * 9600));
>
>It was the multiply that was overflowing and giving the warning.
>Thanks,
>JoeW
>
>--- In 68HC12@68HC..., BobGardner@a... wrote:
> >
> > In a message dated 5/7/05 1:39:30 P.M. Eastern Daylight Time,
> > wobberj@y... writes:
> >
> > #define BAUD_9600 (4000000 / (16 * 9600));
> >
> > The warning is:
> > Warning[Pe061]: integer operation result is out of range
> >
> > My question is:
> > Why does the compiler care? shouldn't the pre-processor
> > evaluate the constant expression _before_ the data type
> > is determined to be insufficient to hold the result


Why don't you just enter 26 instead?
Gary Schnabl
(Southwest) Detroit
2 miles NORTH! of Canada -- Windsor, that is...



--- In 68HC12@68HC..., Gary Schnabl <gschnabl@L...> wrote:
> At 08:10 PM 05/07/2005, you wrote:
>
> >Hi,
> >I found that the following cast works:
> >
> >#define BAUD_9600 (4000000 / ((long) 16 * 9600));
> >

>
> Why don't you just enter 26 instead?
>

Getting ready to use the PLL, so it is actually:
#define BAUD_9600 (BUS_CLOCK / ((long) 16 * 9600));

I just was trying to simplify the original problem by
using a number instead of another macro.

JoeW



--- In 68HC12@68HC..., BobGardner@a... wrote:
>
> In a message dated 5/7/05 1:39:30 P.M. Eastern Daylight Time,
> wobberj@y... writes:
>
> #define BAUD_9600 (4000000 / (16 * 9600));
>
> The warning is:
> Warning[Pe061]: integer operation result is out of range
>
> My question is:
> Why does the compiler care? shouldn't the pre-processor
> evaluate the constant expression _before_ the data type
> is determined to be insufficient to hold the result?
>

Hey Bob,

The preprocessor in fact doesn't care about any types in the above
macro definition and simply inserts the replacement text, i.e.
(4000000/(16*9600)), wherever it finds the token BAUD_9600 in your
source. The reason the compiler cares is because in this case the
integer constant literals are assigned the smallest integer type(not
char or short) that can hold the constant literal so all of the
literals above seem to be assigned 'int' type by your compiler. As
you discovered, by casting one of the literals to (long) causes the
others to be promoted as well and thus avoid overflow and compiler
warnings.

Hope that clears some of the mystery up.




> -----Original Message-----
> From: 68HC12@68HC...
> [mailto:68HC12@68HC...]On Behalf Of
> WobberJ
> Sent: Saturday, May 07, 2005 6:11 PM
> To: 68HC12@68HC...
> Subject: [68HC12] Re: defining constant for use as an int > Hi,
> I found that the following cast works:
>
> #define BAUD_9600 (4000000 / ((long) 16 * 9600));
>
> It was the multiply that was overflowing and giving the warning.
> Thanks,
> JoeW
>
Not quite. It was not the multiply it was the whole equation.
By using a cast to long, you are forcing all the computations to
be promoted to long.

This would be a better way to write it:
#define BAUD_9600 ((unsigned short) (4000000L / (16L * 9600L)));

Most 'C' compilers use int as the default constant type, unless
they are told to use something else (ie. appending an L, or putting a
decimal point in the value).

Hope this helps,

Mike Anton



--- In 68HC12@68HC..., BobGardner@a... wrote:
>
> In a message dated 5/7/05 1:39:30 P.M. Eastern Daylight Time,
> wobberj@y... writes:
>
> #define BAUD_9600 (4000000 / (16 * 9600));
>
> The warning is:
> Warning[Pe061]: integer operation result is out of range
>
> My question is:
> Why does the compiler care? shouldn't the pre-processor
> evaluate the constant expression _before_ the data type
> is determined to be insufficient to hold the result? >
>
> ==========================
> Maybe the preprocesser evals all expressions as int? >


The C standard says that if both of two operands in an expression is
of the same integer type, then no convertion will be done. And sence
both operands 16 and 9600 are small enough to fit into the default
type "int", the result will also be "int". It doesn't matter which
operator that is used. So one or both operands needs to be typecasted
into a "long" on a 16-bit system.


Gary Schnabl <gschnabl@gsch...> wrote:

> >#define BAUD_9600 (4000000 / ((long) 16 * 9600));

[...]

> Why don't you just enter 26 instead?

Because it's bad style and hard to understand and maintain. Numerical
literals are evil, precomputed literals even worse.

BTW: "4000000" should be also a macro defined in some hardware
abstraction file. Else, if "JoeW" changes the clock frequency, he had
to hunt for literals again.

Oliver
--
Oliver Betz, Muenchen


At 11:04 AM 05/09/2005, you wrote:

>Gary Schnabl <gschnabl@gsch...> wrote:
>
> > >#define BAUD_9600 (4000000 / ((long) 16 * 9600));
>
>[...]
>
> > Why don't you just enter 26 instead?
>
>Because it's bad style and hard to understand and maintain. Numerical
>literals are evil, precomputed literals even worse.
>
>BTW: "4000000" should be also a macro defined in some hardware
>abstraction file. Else, if "JoeW" changes the clock frequency, he had
>to hunt for literals again.
>
>Oliver


Roger that! I understand the documentation value of his computation.
Besides, there's no penalty for having the preprocessor & compiler crank
out the math. Furthermore, I was unaware that the 4 MHz was also a value of
another (unmentioned) macro. However, if he was dead-set on using that
particular clock frequency, the assignment of 26 could be done once and for
all, and he could still document this via comments.

I use CodeWarrior for programming the HC(S)12 and usually set the prescaler
bits either at once by assigning the appropriate value in the register
along with the other fields in this register or by setting the appropriate
value into the prescaler field of this register. The BAUD_9600 is most
probably this same field. Also the RAD Processor Expert in CodeWarrior can
automatically be used for making this assignment. Gary Schnabl
(Southwest) Detroit
2 miles NORTH! of Canada -- Windsor, that is...