By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,421 Members | 1,127 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,421 IT Pros & Developers. It's quick & easy.

printf anomaly

P: n/a
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,

Feb 22 '07 #1
Share this Question
Share on Google+
10 Replies


P: n/a
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

Feb 22 '07 #2

P: n/a
in*******@yahoo.com wrote:
>
unsigned long data = 0x124

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.

--
pete
Feb 22 '07 #3

P: n/a
in*******@yahoo.com writes:
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.

--
Keith Thompson (The_Other_Keith) 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.
Feb 22 '07 #4

P: n/a
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

Feb 22 '07 #5

P: n/a
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,
Feb 22 '07 #6

P: n/a
in*******@yahoo.com wrote:
>
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.

--
pete
Feb 22 '07 #7

P: n/a
in*******@yahoo.com wrote, On 22/02/07 02:21:
>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.
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.
--
Flash Gordon
Feb 22 '07 #8

P: n/a
On 21 Feb 2007 17:24:14 -0800, in*******@yahoo.com wrote in
comp.lang.c:
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.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Feb 22 '07 #9

P: n/a
in*******@yahoo.com wrote:
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.

--
DPS
Feb 22 '07 #10

P: n/a
in*******@yahoo.com wrote:
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?

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Feb 23 '07 #11

This discussion thread is closed

Replies have been disabled for this discussion.