LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-04-2009, 09:30 AM   #1
yanivwehtam
LQ Newbie
 
Registered: Mar 2009
Posts: 6

Rep: Reputation: 0
printing 64bit integers in C


Hi All,
I am aware that this question has been asked before and I have also tried the solution suggested but I am still not able to figure it out why I am getting some wierd results when I am using printf with a 64 bit signed and unsigned integer in C.
I am running Suse 10.2 on a Intel(R) Pentium(R) M processor 2 GHz.

I tried to call functions strtol strtoll strtoul and strtoull with different integer sizes and these are the results i get from my program shown below:

int i;
char str[100];
char endstr[100];
int64_t ret_val = 0LL;
int32_t retval = 0;
uint64_t uret_val = 0UL;
uint32_t uretval = 0;

strcpy(str, "11221212122121 final string");
strcpy(endstr, "");
ret_val = strtoll(str, &endstr, 3);
printf("64bit Size:%d Returned Val strtoll:%016x %lld Endptr:%s\n",sizeof(int64_t), ret_val, ret_val, endstr);

//ret_val = __INT64_C(28346590832469346);
//printf("%lld\n",ret_val);

strcpy(str, "11221212122121 final string");
strcpy(endstr, "");
retval = strtol(str, &endstr, 3);
printf("32bit Size:%d Returned Val strtol:%08x %ld Endptr:%s\n",sizeof(int32_t), retval, retval, endstr);


strcpy(str, "47483649");
strcpy(endstr, "");
uret_val = strtoull(str, &endstr, 0);
printf("64bit Size:%d Returned Val strtoull:%016x %llu \n",sizeof(uint64_t), uret_val, uret_val);

strcpy(str, "47483649");
strcpy(endstr, "");
uretval = strtoul(str, &endstr, 0);
printf("32bit Size:%d Returned Val strtoul:%08x %lu Endptr:%s\n",sizeof(uint32_t), uretval, uretval, endstr);


The results i get from this piece of code is shown below:
64bit Size:8 Returned Val strtoll:0000000000283549(HEX) 11317586717310976 Endptrnull)
32bit Size:4 Returned Val strtol:00283549(HEX) 2635081 Endptr:�V����
64bit Size:8 Returned Val strtoull:0000000002d48b01(HEX) 203940719549743104
32bit Size:4 Returned Val strtoul:02d48b01(HEX) 47483649 Endptr:�V����


What I cannot figure out is why the printf %lld and %llu for int64_t and uint64_t always give some wierd values as the result. For both variants of the strtol,strtoll and strtoul,strtoull functions the HEX value returned is the same as expected whereas the decimal value for strtoll and strtoull is completely different. I am not able to figure out the reason behind this. I am sure there is a logical explanation to the problem but I am just not able to see it. Have googled on this almost the whole day now. I am using the gcc 4.2.1 compiler on Suse 10.2 Linux distribution.

Thanks a million
cheers
vinay
 
Old 03-04-2009, 09:55 AM   #2
fantas
Member
 
Registered: Jun 2007
Location: Bavaria
Distribution: slackware, xubuntu
Posts: 143

Rep: Reputation: 22
Firstly, the second parameter to strtol(l) is a pointer to a pointer of type char, not a pointer to an array. It merely serves to get a pointer to the end of the string back to the caller. You can also just use NULL and it will be ignored.

Secondly, the third paramter to strtol(l) is the base to which the number is calculated, e.g. for decimals you need to put in a 10 or for hexadecimals a 16.

You should read up on the exact use of those functions. A good ressource has always been
http://www.cplusplus.com/reference/c...ib/strtol.html

HTH,
f
 
Old 03-04-2009, 10:34 AM   #3
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
I was about to comment on the wrong second parameter, but I see that is covered already, and it's not the serious problem.

Quote:
Originally Posted by yanivwehtam View Post
printf("64bit Size:%d Returned Val strtoll:%016x %lld Endptr:%s\n",sizeof(int64_t), ret_val, ret_val, endstr);
Always carefully match the value arguments in the printf to the format string. You would notice the error.

%d goes with sizeof(int64_t), both are 32bit so OK.
%016x goes with ret_val. %016x is 32 bit so it gets the low half of the 64 bit value.
%lld goes with the next ret_val, but first it takes the left over 32 bits from the first one, so you get 2**32 times the expected result.
%s goes with endstr, which would be garbage because of the other bug, but is different garbage because of the left over 32 bits.

Quote:
Originally Posted by yanivwehtam View Post
What I cannot figure out is why the printf %lld and %llu for int64_t and uint64_t always give some wierd values as the result.
Because of the extra 32 bits from the earlier error.

Quote:
For both variants of the strtol,strtoll and strtoul,strtoull functions the HEX value returned is the same as expected
It is only same as expected when the expected 64 bit value fits in 32 bits. The fact that you asked for 16 digits of hex output does not change the fact that it is using only 32 bits of input.

Quote:
I am using the gcc 4.2.1 compiler on Suse 10.2 Linux distribution.
The very relevent detail I deduce from your results (but don't see explicit) is that you are compiling x86, not x86_64.

In x86_64 your main error would have less consequence. In x86_64 ints are still 32bit, but they take 64bits of space when passed to a function. So the fact that %x consumes only 32bits would not cause the remaining 32bits to be left over. The remaining 32bits would be skipped.

Since I see the extra 32 bits aren't skipped, I deduce you are using a 32 bit compile.

Last edited by johnsfine; 03-04-2009 at 10:42 AM.
 
Old 03-04-2009, 10:55 AM   #4
fantas
Member
 
Registered: Jun 2007
Location: Bavaria
Distribution: slackware, xubuntu
Posts: 143

Rep: Reputation: 22
I'm amazed that the program didn't just core dump but still gave a printout, especially after calling strtol(l) with a base 0 (come to think of it - probably a sanity check inside the clib function prevented worse to happen).
EDIT: Ok, I just read, it seems to default to decimal behaviour in this case.

Last edited by fantas; 03-04-2009 at 10:58 AM.
 
Old 03-05-2009, 02:25 AM   #5
yanivwehtam
LQ Newbie
 
Registered: Mar 2009
Posts: 6

Original Poster
Rep: Reputation: 0
Hi Guys,
Thanks a million for the response. I realised the GRAVE mistakes I had made in that code. But coming back to C after a long time I think i needed to refresh some of my grey matter in C.
Just out of curiosity,
1) The ret_val variable is declared as int64_t. Isnt this enough for the compiler to note that it has to reserve 64 bits of space when passing this argument to the printf call? So if I just specify %x or %d, I would expect that the lower 32 bits are displayed and the remaining 32 bits are ignored as i thought would be the case by the printf call above or am i missing something fundamental here.
2) does the standard printf function have options to display integers in bases other than hex and decimal? Or one has to implement ones own custom print function to print numbers in different bases?
Thanks and cheers
 
Old 03-05-2009, 07:48 AM   #6
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by yanivwehtam View Post
1) The ret_val variable is declared as int64_t. Isnt this enough for the compiler to note that it has to reserve 64 bits of space when passing this argument
Note where?

The compiler knows it has used 64 bits when passing ret_val, but there is no mechanism in C for the compiler to give that fact to printf. So printf doesn't know the second value is 64 bits.

In the C standard, the compiler doesn't know that the first argument to printf is a format string, nor does it know that %x in a format string should correspond to a 32 bit value (in this architecture) in the value list.

But (I think) there is an option to gcc to have it know things like that, and generate warnings when the values you give to printf aren't compatible with the format string. It still can't fix the way printf acts nor change the way the values are passed. But it can at least tell you that you made a mistake.

Quote:
if I just specify %x or %d, I would expect that the lower 32 bits are displayed and the remaining 32 bits are ignored as i thought would be the case by the printf call above or am i missing something fundamental here.
Are you still missing something fundamental?
printf has nothing other than the format string to tell it the sizes or types of the values that were passed. If the actual sizes or types are different from what the format string specifies, printf has no way to ignore extra stuff in the middle.

Quote:
2) does the standard printf function have options to display integers in bases other than hex and decimal? Or one has to implement ones own custom print function to print numbers in different bases?
I don't know. Maybe someone else still reading this thread knows.

Last edited by johnsfine; 03-05-2009 at 08:58 AM.
 
Old 03-05-2009, 08:56 AM   #7
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
To OP: first and foremost use -Wall -Wextra on 'gcc' command line.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
How do I resolve install DB2v9.5 64bit/RHEL 5 64bit (libstdc++.so.5 is not found)? okonita Linux - Newbie 2 11-13-2008 02:15 AM
Can't install amarok 64bit du eto missing provider of libpq.so.4()(64bit) Ossah Linux - Software 1 04-21-2007 09:23 PM
64-bit integers in C nodger Programming 1 03-31-2005 08:06 AM
converting integers to strings 1337 Twinkie Programming 12 08-06-2004 04:57 PM
allegro + hex integers CamelofCamelot Programming 4 01-04-2004 09:56 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 01:19 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration