printf anomaly

I

indigodfw

Hi experts

Consider this piece of code

unsigned long data = 124; /* Data is actually part of a big struct but
to simplify */
printf(" %-5llu ", (unsigned long long)(data*1000));


<memory address say 60000000>: 00000000 00000D77 00000000
00000000
0xD77 is 3447

Assume data is at the beginning of memory address 60000000 and this is
a big endian machine (MIPS based).
The compiler is doing two load word from 60000000 and 60000000+4 and
then multiplying it by 1000 and then prints 3447000 which is not
expected.

My understanding is that the 1000 will default to int
Then it will be promoted to unsigned long (since on our platform long
and int are of same size)
then operation will be carried out in unsigned long (result I mean).
then *result* will be cast to unsigned long long and then it will be
passed to printf
(not sure how - this is MIPS based platform) and printf is a variadic
function.

I must be missing something or the compiler is broken?

1.Please help me understand what is going on.
2.And how can I fix it the right way.

Please advise.
Thanks in advance,
 
I

indigodfw

unsigned long data = 0x124

please ignore the above initialization line in previous post.
I only wanted to say : the type of data is unsigned long.
Thanks
 
P

pete

please ignore the above initialization line in previous post.

That line wasn't in your previous post.
I only wanted to say : the type of data is unsigned long.

You do need to say more than the type of the data.
The nature of your complaint is the output of printf,
which also depends on the value of data.

Create and post the smallest program that still exhibits your problem.
Try to use copy and paste facilities or something equivalent,
instead of posting you recollections
of what the code may have looked like.
 
K

Keith Thompson

Consider this piece of code

unsigned long data = 124; /* Data is actually part of a big struct but
to simplify */
printf(" %-5llu ", (unsigned long long)(data*1000));


<memory address say 60000000>: 00000000 00000D77 00000000
00000000
0xD77 is 3447

Assume data is at the beginning of memory address 60000000 and this is
a big endian machine (MIPS based).
The compiler is doing two load word from 60000000 and 60000000+4 and
then multiplying it by 1000 and then prints 3447000 which is not
expected.

My understanding is that the 1000 will default to int
Then it will be promoted to unsigned long (since on our platform long
and int are of same size)
then operation will be carried out in unsigned long (result I mean).
then *result* will be cast to unsigned long long and then it will be
passed to printf
(not sure how - this is MIPS based platform) and printf is a variadic
function.

I must be missing something or the compiler is broken?

In a followup you wrote:
| > unsigned long data = 0x124
|
| please ignore the above initialization line in previous post.
| I only wanted to say : the type of data is unsigned long.

But in your original post, data was initialized to 124, not 0x124.
The fact that you misquoted your own post doesn't fill me with
confidence that you've shown us your actual code and data. You show a
printf call with a format of "%-5llu", but your output is in
hexadecimal with leading zeros.

I can't tell from what you posted what the problem might be. Post a
small complete program that exhibits the problem, along with the
actual output and what you expected the output to be. Don't re-type
either the program or the output; copy-and-paste it exactly.
 
I

indigodfw

Pete,

Sure, let me try again.

printf(" %-5llu ", (unsigned long long)(data*1000));

<16 byts of memory starting at 0x60000000 in hex>:
00000000 00000D77 00000000 00000000

data is a unsigned long 4 byte variable starting at 0x60000000
This is a big endian cpu and address is incrementing for the above
memory dump.
0xD77 is 3447 in decimal.

The output printed is 3447000 in decimal and expected output is zero.
I would like to understand what is happening.

Thank you,
-Sushil
 
I

indigodfw

But in your original post, data was initialized to 124, not 0x124.
The fact that you misquoted your own post doesn't fill me with
confidence that you've shown us your actual code and data. You show a
printf call with a format of "%-5llu", but your output is in
hexadecimal with leading zeros.


Keith,

This is running on an embedded system and I can not copy the output.
What I pasted was dump of memory as seen from a debugger, not a
printed output.

Thanks for the reply,
 
P

pete

Pete,

Sure, let me try again.

printf(" %-5llu ", (unsigned long long)(data*1000));

<16 byts of memory starting at 0x60000000 in hex>:
00000000 00000D77 00000000 00000000

data is a unsigned long 4 byte variable starting at 0x60000000
This is a big endian cpu and address is incrementing for the above
memory dump.
0xD77 is 3447 in decimal.

The output printed is 3447000 in decimal and expected output is zero.
I would like to understand what is happening.

Post a complete program.
 
F

Flash Gordon

Keith,

This is running on an embedded system and I can not copy the output.

You can copy and paste the program which evidence suggests you did not do.
What I pasted was dump of memory as seen from a debugger, not a
printed output.

Anything could be going on in memory. All we can comment on is what the
output of the printf call should be on a hosted implementation (if it is
not hosted it is not even required to provide printf), and then only if
we are given a *complete* compilable program.
 
J

Jack Klein

Hi experts

Consider this piece of code

unsigned long data = 124; /* Data is actually part of a big struct but
to simplify */

I understand that in a later post you day that the initialization line
above is not correct, and to just assume that you meant to define
"data" as having the type unsigned long.

Unfortunately, in your later post and replies to other respondents you
do not leave enough context to add additional replies.
printf(" %-5llu ", (unsigned long long)(data*1000));


<memory address say 60000000>: 00000000 00000D77 00000000
00000000
0xD77 is 3447

I have no idea what this means, memory dumps are not relevant.
Assume data is at the beginning of memory address 60000000 and this is
a big endian machine (MIPS based).

Why should I assume that? You appear to assume that, and because of
that you assume that the compiler is doing something wrong.
The compiler is doing two load word from 60000000 and 60000000+4 and
then multiplying it by 1000 and then prints 3447000 which is not
expected.

How the compiler chooses to access the contents of lvalues is up to
the compiler. If you are sure it is incorrect you need to contact the
compiler supplier.
My understanding is that the 1000 will default to int
Then it will be promoted to unsigned long (since on our platform long
and int are of same size)

Your understanding is wrong. The type of the integer literal
expression "1000" is int, no default involved. You are also wrong in
thinking that the sizes of int and long have anything to do with the
automatic conversion. When you perform an operation on a signed int
and an unsigned long, the signed int value will be converted to
unsigned long regardless of whether the sizes are the same or
different.
then operation will be carried out in unsigned long (result I mean).
then *result* will be cast to unsigned long long and then it will be
passed to printf

So exactly what are you concerned about? 1000UL * 3447UL = 3447000UL,
which is a value that clearly fits in an unsigned long. The cast
operator converts this unsigned long long, in which it will surely fit
and have the same value.
(not sure how - this is MIPS based platform) and printf is a variadic
function.

I must be missing something or the compiler is broken?

We're missing something, namely the information that you did not
provide. Don't show us a hexadecimal dump of what you think is the
relevant part of memory, that is irreverent.

Are you claiming that the value of "data" is not 3447? How do you
know?

Show us the output of this code:

printf("%lu", data);
printf("%llu", (unsigned long long)(data*1000))

1.Please help me understand what is going on.
2.And how can I fix it the right way.

Even better, show us the structure definition and how the object is
actually accessed in the code, without the simplification.

I have seen cases where an access to a structure member actually
access the wrong bytes of the object. This is most common when people
play games with pointers and make mistakes or have incorrect
assumptions, but there are other possible causes.
 
D

Dietmar Schindler

Consider this piece of code

unsigned long data = 124; /* Data is actually part of a big struct but
to simplify */
printf(" %-5llu ", (unsigned long long)(data*1000));

<memory address say 60000000>: 00000000 00000D77 00000000
00000000
0xD77 is 3447

Assume data is at the beginning of memory address 60000000 and this is
a big endian machine (MIPS based).
The compiler is doing two load word from 60000000 and 60000000+4 and
then multiplying it by 1000 and then prints 3447000 which is not
expected.

My understanding is that the 1000 will default to int
Then it will be promoted to unsigned long (since on our platform long
and int are of same size)
then operation will be carried out in unsigned long (result I mean).
then *result* will be cast to unsigned long long and then it will be
passed to printf
(not sure how - this is MIPS based platform) and printf is a variadic
function.

I must be missing something or the compiler is broken?

1.Please help me understand what is going on.

What you are missing could be the knowledge that sizeof (unsigned long)
is 8.
2.And how can I fix it the right way.

There would be nothing wrong and nothing to fix.
 
J

Joe Wright

Pete,

Sure, let me try again.

printf(" %-5llu ", (unsigned long long)(data*1000));

<16 byts of memory starting at 0x60000000 in hex>:
00000000 00000D77 00000000 00000000

data is a unsigned long 4 byte variable starting at 0x60000000
This is a big endian cpu and address is incrementing for the above
memory dump.
0xD77 is 3447 in decimal.

The output printed is 3447000 in decimal and expected output is zero.
I would like to understand what is happening.

So data occupies 8 bytes. 0x0000000000000d77 which is 3447 and when
multiplied by 1000 yields 3447000. What's the problem?
 

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

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,678
Members
48,796
Latest member
Greg L.

Latest Threads

Top