473,394 Members | 1,829 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

hex and unsigned and signed decimal

me2
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
Dec 28 '06 #1
14 14188

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.

Dec 28 '06 #2

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.

Dec 28 '06 #3

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.

Dec 28 '06 #4
me2
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.
Dec 28 '06 #5
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>
Dec 28 '06 #6
me2 <no****@nowhere.comwrites:
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--
Dec 29 '06 #7
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
Dec 29 '06 #8
me2
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 ?
Dec 29 '06 #9
me2
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.
Dec 29 '06 #10
me2 <no****@nowhere.comwrites:
0xffffff81 is a 32 bit number. How can it be integer overflow ?
And its value is +0xffffff81, not -0x7f or whatever you are thinking of.
On a host where 'int' is 32-bit, there are only 31 bits to store the
absolute value in, and that is not enough for +0xffffff81. Thus,
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 ?
No, that's what the host is _not_ required to do, which is why you can't
rely on any particular result. But yes, overflow _into_ the sign bit
is still overflow.

--
Hallvard
Dec 29 '06 #11
me2 writes:
Changing it to use strtol and a long prevented the overflow. It works
properly now.
Maybe 'long' is wider than 'int' on your host, then. If that's the
reason it works, it will break on hosts where both are the same size -
which is legal and quite common. (For that matter 'long long' is not
required to be wider than 'int' either, but at least I don't know of any
counterexamples.)

--
Hallvard
Dec 29 '06 #12
Hallvard B Furuseth <h.**********@usit.uio.nowrites:
me2 writes:
>Changing it to use strtol and a long prevented the overflow. It works
properly now.

Maybe 'long' is wider than 'int' on your host, then. If that's the
reason it works, it will break on hosts where both are the same size
Then strtol() will set errno to appropriate value and thus program
will print error message instead of printing wrong value (I hope).

--
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--
Dec 31 '06 #13
>me2 wrote:
>... 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 ?
In article <11**********************@h40g2000cwb.googlegroups .com>
Scorpio <av*******@gmail.comwrote:
>Because %i is ...
Right start, but:
>only for integers.
wrong details. :-)

All of this family of conversions -- %d, %i, %o, %u, and %x -- are
"for integers", specifically for int unless modified (e.g., %lu is
for long, %hx is for short; note that the hh and ll modifiers are
specific to C99). All of them also convert "as if" by strtol() or
strtoul() -- or in C99 sometimes strtoll() and strtoull() -- with
a base of 16, 10, 8, or 0 depending on the conversion directive;
except that in all cases, the behavior is not defined if the number
would overflow.

Most implementations seem to use the strtol() family of functions
internally, so that they all exhibit that family's "clamping"
behavior of out-of-range inputs. This is the case above: 0xffffff81
is (presuambly) out of range for strtol(), and %i reads a *signed*
integer, so the input is clamped to INT_MAX (or more likely to
LONG_MAX, but that is probably the same as INT_MAX on the target
platform).
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jan 2 '07 #14
Chris Torek <no****@torek.netwrites:
[...]
All of this family of conversions -- %d, %i, %o, %u, and %x -- are
"for integers", specifically for int unless modified (e.g., %lu is
for long, %hx is for short; note that the hh and ll modifiers are
specific to C99).
[...]

Quibble: %d and %i are for int, %o, %u, and %x are for unsigned int.

--
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.
Jan 2 '07 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

19
by: MiniDisc_2k2 | last post by:
Okay, here's a question about the standard. What does it say about unsigned/signed mismatches in a comparison statement: char a = 3; unsigned char b = 255; if (a<b) Now what's the real...
4
by: Ken Tough | last post by:
Seems like a simple thing to find out, but I'm struggling. I have googled, but everything I find is about implicit conversion, not explicit. Is this implementation-specific, or does ANSI/ISO...
7
by: HH | last post by:
int main() { uint x = -1; int y = -1; if (x == y) printf("EQUAL"); else printf("NOT EQUAL"); } This code prints "EQUAL". Does this mean that bit comparison is done for the
4
by: Sam | last post by:
Hi, I am using some functions return a base64 encoded string. The functions write it into an unsigned char buffer. I am a little confused as to why a base64 encoded string would be using an...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.