Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > hex and unsigned and signed decimal

Reply
Thread Tools

hex and unsigned and signed decimal

 
 
me2
Guest
Posts: n/a
 
      12-28-2006
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
 
Reply With Quote
 
 
 
 
Scorpio
Guest
Posts: n/a
 
      12-28-2006

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.

 
Reply With Quote
 
 
 
 
Scorpio
Guest
Posts: n/a
 
      12-28-2006

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.

 
Reply With Quote
 
Scorpio
Guest
Posts: n/a
 
      12-28-2006

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.

 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      12-28-2006
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>


 
Reply With Quote
 
me2
Guest
Posts: n/a
 
      12-28-2006
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.
 
Reply With Quote
 
Michal Nazarewicz
Guest
Posts: n/a
 
      12-29-2006
me2 <(E-Mail Removed)> 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--
 
Reply With Quote
 
Hallvard B Furuseth
Guest
Posts: n/a
 
      12-29-2006
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
 
Reply With Quote
 
me2
Guest
Posts: n/a
 
      12-29-2006
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 ?
 
Reply With Quote
 
me2
Guest
Posts: n/a
 
      12-29-2006
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.
 
Reply With Quote
 
 
 
Reply

Thread Tools

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 On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
(int) -> (unsigned) -> (int) or (unsigned) -> (int) -> (unsigned):I'll loose something? pozz C Programming 12 03-20-2011 11:32 PM
Convert a signed binary number into a signed one ? Rob1bureau VHDL 1 02-27-2010 12:13 AM
signed(12 downto 0) to signed (8 downto 0) kyrpa83 VHDL 1 10-17-2007 06:58 PM
Hex Color Codes - Hex 6 <=> Hex 3 lucanos@gmail.com HTML 10 08-18-2005 11:21 PM
hex(-5) => Futurewarning: ugh, can't we have a better hex than '-'[:n<0]+hex(abs(n)) ?? Bengt Richter Python 6 08-19-2003 07:33 AM



Advertisments