![]() |
hex and unsigned and signed decimal
I am writing a little base conversion utility called base.c.
This is what base does. $ base -127 Signed decimal: -127 Unsigned decimal: 4294967169 Hexidecimal: 0xffffff81 Octal: O37777777601 Binary: 1098 7654 3210 9876 5432 1098 7654 3210 1111 1111 1111 1111 1111 1111 1000 0001 $ base 127 Signed decimal: 127 Unsigned decimal: 127 Hexidecimal: 0x7f Octal: O177 Binary: 1098 7654 3210 9876 5432 1098 7654 3210 0000 0000 0000 0000 0000 0000 0111 1111 However, base has a bug when one inputs sign extended hexadecimal or octal numbers, like this. $ base 0xffffff81 Signed decimal: 2147483647 Unsigned decimal: 2147483647 Hexidecimal: 0x7fffffff Octal: O17777777777 Binary: 1098 7654 3210 9876 5432 1098 7654 3210 0111 1111 1111 1111 1111 1111 1111 1111 Base works like this. I use sscanf %i to convert argv[1] to an int. Then I cast the int to an unsigned int and do the rest of the manipulation. However, as the above example shows, it doesn't work properly when I input a sign extended octal or hex number. The decimal of 0xffffff81 should be 4294967169, but it isn't. Why ? Thanks |
Re: hex and unsigned and signed decimal
me2 wrote: > I am writing a little base conversion utility called base.c. > > This is what base does. > > $ base -127 > Signed decimal: -127 > Unsigned decimal: 4294967169 > Hexidecimal: 0xffffff81 > Octal: O37777777601 > Binary: 1098 7654 3210 9876 5432 1098 7654 3210 > 1111 1111 1111 1111 1111 1111 1000 0001 > $ base 127 > Signed decimal: 127 > Unsigned decimal: 127 > Hexidecimal: 0x7f > Octal: O177 > Binary: 1098 7654 3210 9876 5432 1098 7654 3210 > 0000 0000 0000 0000 0000 0000 0111 1111 > > However, base has a bug when one inputs sign extended hexadecimal or octal > numbers, like this. > > $ base 0xffffff81 > Signed decimal: 2147483647 > Unsigned decimal: 2147483647 > Hexidecimal: 0x7fffffff > Octal: O17777777777 > Binary: 1098 7654 3210 9876 5432 1098 7654 3210 > 0111 1111 1111 1111 1111 1111 1111 1111 > > Base works like this. I use sscanf %i to convert argv[1] to an int. Then > I cast the int to an unsigned int and do the rest of the manipulation. > However, as the above example shows, it doesn't work properly when I input > a sign extended octal or hex number. > > The decimal of 0xffffff81 should be 4294967169, but it isn't. Why ? Because %i is only for integers. You will need to check the string in argv[1] before scanning it using sscanf. If it is preceded with "0x" then use %x (hexadecimal), if its preceded with just "0" then use %o (octal) for scanning with sprintf, and later you can convert it to other formats. |
Re: hex and unsigned and signed decimal
Scorpio wrote: > me2 wrote: > > I am writing a little base conversion utility called base.c. > > > > This is what base does. > > > > $ base -127 > > Signed decimal: -127 > > Unsigned decimal: 4294967169 > > Hexidecimal: 0xffffff81 > > Octal: O37777777601 > > Binary: 1098 7654 3210 9876 5432 1098 7654 3210 > > 1111 1111 1111 1111 1111 1111 1000 0001 > > $ base 127 > > Signed decimal: 127 > > Unsigned decimal: 127 > > Hexidecimal: 0x7f > > Octal: O177 > > Binary: 1098 7654 3210 9876 5432 1098 7654 3210 > > 0000 0000 0000 0000 0000 0000 0111 1111 > > > > However, base has a bug when one inputs sign extended hexadecimal or octal > > numbers, like this. > > > > $ base 0xffffff81 > > Signed decimal: 2147483647 > > Unsigned decimal: 2147483647 > > Hexidecimal: 0x7fffffff > > Octal: O17777777777 > > Binary: 1098 7654 3210 9876 5432 1098 7654 3210 > > 0111 1111 1111 1111 1111 1111 1111 1111 > > > > Base works like this. I use sscanf %i to convert argv[1] to an int. Then > > I cast the int to an unsigned int and do the rest of the manipulation. > > However, as the above example shows, it doesn't work properly when I input > > a sign extended octal or hex number. > > > > The decimal of 0xffffff81 should be 4294967169, but it isn't. Why ? > > Because %i is only for integers. You will need to check the string in > argv[1] before scanning it using sscanf. If it is preceded with "0x" > then use %x (hexadecimal), if its preceded with just "0" then use %o > (octal) for scanning with sprintf, and later you can convert it to > other formats. Correction...I meant scanning with sscanf, not sprintf. Sorry. |
Re: hex and unsigned and signed decimal
Scorpio wrote: > Scorpio wrote: > > me2 wrote: > > > I am writing a little base conversion utility called base.c. > > > > > > This is what base does. > > > > > > $ base -127 > > > Signed decimal: -127 > > > Unsigned decimal: 4294967169 > > > Hexidecimal: 0xffffff81 > > > Octal: O37777777601 > > > Binary: 1098 7654 3210 9876 5432 1098 7654 3210 > > > 1111 1111 1111 1111 1111 1111 1000 0001 > > > $ base 127 > > > Signed decimal: 127 > > > Unsigned decimal: 127 > > > Hexidecimal: 0x7f > > > Octal: O177 > > > Binary: 1098 7654 3210 9876 5432 1098 7654 3210 > > > 0000 0000 0000 0000 0000 0000 0111 1111 > > > > > > However, base has a bug when one inputs sign extended hexadecimal or octal > > > numbers, like this. > > > > > > $ base 0xffffff81 > > > Signed decimal: 2147483647 > > > Unsigned decimal: 2147483647 > > > Hexidecimal: 0x7fffffff > > > Octal: O17777777777 > > > Binary: 1098 7654 3210 9876 5432 1098 7654 3210 > > > 0111 1111 1111 1111 1111 1111 1111 1111 > > > > > > Base works like this. I use sscanf %i to convert argv[1] to an int. Then > > > I cast the int to an unsigned int and do the rest of the manipulation. > > > However, as the above example shows, it doesn't work properly when I input > > > a sign extended octal or hex number. > > > > > > The decimal of 0xffffff81 should be 4294967169, but it isn't. Why ? > > > > Because %i is only for integers. You will need to check the string in > > argv[1] before scanning it using sscanf. If it is preceded with "0x" > > then use %x (hexadecimal), if its preceded with just "0" then use %o > > (octal) for scanning with sprintf, and later you can convert it to > > other formats. > > Correction...I meant scanning with sscanf, not sprintf. Sorry. More correction. I just realized that %x and %o are only for printing, and its cannot be used for scanning. So you'll have to find some other method to read hexadecimal and octal values. |
Re: hex and unsigned and signed decimal
me2 wrote:
> .... snip ... > > However, base has a bug when one inputs sign extended hexadecimal > or octal numbers, like this. > > $ base 0xffffff81 > Signed decimal: 2147483647 > Unsigned decimal: 2147483647 > Hexidecimal: 0x7fffffff > Octal: O17777777777 > Binary: 1098 7654 3210 9876 5432 1098 7654 3210 > 0111 1111 1111 1111 1111 1111 1111 1111 > > Base works like this. I use sscanf %i to convert argv[1] to an > int. Then I cast the int to an unsigned int and do the rest of > the manipulation. However, as the above example shows, it doesn't > work properly when I input a sign extended octal or hex number. > > The decimal of 0xffffff81 should be 4294967169, but it isn't. > Why ? You have experienced integer overflow, after which behaviour is undefined. Therefore the answers you are getting (or anything else) are perfectly valid. -- Merry Christmas, Happy Hanukah, Happy New Year Joyeux Noel, Bonne Annee. Chuck F (cbfalconer at maineline dot net) <http://cbfalconer.home.att.net> |
Re: hex and unsigned and signed decimal
On Thu, 28 Dec 2006 07:04:32 -0800, Scorpio wrote:
> Because %i is only for integers. You will need to check the string in > argv[1] before scanning it using sscanf. If it is preceded with "0x" > then use %x (hexadecimal), if its preceded with just "0" then use %o > (octal) for scanning with sprintf, and later you can convert it to > other formats. But man sscanf says this: The following conversion specifiers are available: .... i Matches an optionally signed integer; the next pointer must be a pointer to int. The integer is read in base 16 if it begins with 0x or 0X, in base 8 if it begins with 0, and in base 10 otherwise. Only characters that correspond to the base are used. So why isn't it properly reading the hex and octal numbers ? Thanks. |
Re: hex and unsigned and signed decimal
me2 <nobody@nowhere.com> writes:
> I am writing a little base conversion utility called base.c. > > This is what base does. [cut] > However, base has a bug when one inputs sign extended hexadecimal or octal > numbers, like this. [cut] > I use sscanf %i to convert argv[1] to an int. You'd better use strtol() for that which can automatically read decimal, octal or hexadecimal numbers and provides better error checking I guess. You could even use strtoll() for bigger numbers if it's available on your system (I believe it's defined in C99). #v+ #include <stdio.h> #include <stdlib.o> #include <errno.h> int main(int argc, char **argv) { char *end; long long num; if (argc!=2) { fputs("usage: base <number>\n", stderr); return EXIT_FAILURE; } num = strtoll(argv[1], &end, 0); if (*end || errno) { fprintf(stder, "%s: invalid number\n", argv[1]); return EXIT_FAILURE; } printf("signed : %lld\n", num); printf("unsigned: %llu\n", num); printf("hex : %llo\n", num); printf("octal : %llx\n", num); return EXIT_SUCESS; } #v- (code not tested) -- Best regards, _ _ .o. | Liege of Serenly Enlightened Majesty of o' \,=./ `o ..o | Computer Science, Michal "mina86" Nazarewicz (o o) ooo +--<mina86*tlen.pl>---<jid:mina86*chrome.pl>--ooO--(_)--Ooo-- |
Re: hex and unsigned and signed decimal
Michal Nazarewicz writes:
> You'd better use strtol() for that which can automatically read > decimal, octal or hexadecimal numbers and provides better error > checking I guess. You could even use strtoll() for bigger numbers if > it's available on your system (I believe it's defined in C99). Or lacking long long, handle the sign specially and read the rest into an unsigned int with strtoul or %u. Then maybe convert to int - taking care to avoid overflow, including for INT_MIN. -- Hallvard |
Re: hex and unsigned and signed decimal
On Thu, 28 Dec 2006 11:14:06 -0500, CBFalconer wrote:
> You have experienced integer overflow, after which behaviour is > undefined. Therefore the answers you are getting (or anything > else) are perfectly valid. 0xffffff81 is a 32 bit number. How can it be integer overflow ? Are you saying it will interpret it as an unsigned integer and then try to stuff it in a signed int variable and overflow that way ? |
Re: hex and unsigned and signed decimal
On Fri, 29 Dec 2006 11:16:00 +0100, Michal Nazarewicz wrote:
Changing it to use strtol and a long prevented the overflow. It works properly now. |
| All times are GMT. The time now is 11:32 AM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.