strtol with hex greater than 4 byte ?

P

Peter Dunker

Hi,

I will check a String which should contain a HEX value.
I know that strtol is the right function for this job.

But what happens when I will check a hex string with 8 bytes?
That I can check that the string is correct i know.

long value;
char src[]="0x1234567812345678"
char *err;
value = strtol(src,&err, 16);
if (*err != 0x00)
return -1; /*FEHLER*/

The value is not 0x12345678 but I know it is right spelled.

Is that C89 standard or only on my compiler/OS (VC6, Windows) ?

Is there a way to get the right value of the beginning of the string,
up to the sizeof(long) ?

Thx
Peter
 
C

Case

Peter said:
Hi,

I will check a String which should contain a HEX value.
I know that strtol is the right function for this job.

But what happens when I will check a hex string with 8 bytes?
That I can check that the string is correct i know.

long value;
char src[]="0x1234567812345678"
char *err;
value = strtol(src,&err, 16);

Note that in this case (string starts with "0x") you could set
base to 0 and let strtol() figure it out. Just a remark; being
explicit is usually a good programming habit. :)
if (*err != 0x00)
return -1; /*FEHLER*/

The value is not 0x12345678 but I know it is right spelled.

Is that C89 standard or only on my compiler/OS (VC6, Windows) ?

Unless long is 64-bit on your platform (which I assume is not, but
rather 32-bit), strtol() processes the full src[] and overflows.
According to K&R, page 252 LONG_MAX is returned, which is indeed
not equal to 0x12345678. Also errno is set to ERANGE.
Is there a way to get the right value of the beginning of the string,
up to the sizeof(long) ?

Not that I know of, using standard library functions. In that case you
must do it yourself. You could for example make a copy of the string
up to sizeof long bytes and pass that copy to strtol().
 
P

Peter Dunker

Case said:
Peter said:
Hi,

I will check a String which should contain a HEX value.
I know that strtol is the right function for this job.

But what happens when I will check a hex string with 8 bytes?
That I can check that the string is correct i know.

long value;
char src[]="0x1234567812345678"
char *err;
value = strtol(src,&err, 16);

Note that in this case (string starts with "0x") you could set
base to 0 and let strtol() figure it out. Just a remark; being
explicit is usually a good programming habit. :)
I know the possibility with 0, but the string should/must be a hex
value, if there is a possibilty to get the used base after strtol is
done, that will be create, but I don't think so.
I have written a big "if" with str[0] and str[1] to check a x X 0x 0X
at the beginning of the string and do then the strtol.
if (*err != 0x00)
return -1; /*FEHLER*/

The value is not 0x12345678 but I know it is right spelled.

Is that C89 standard or only on my compiler/OS (VC6, Windows) ?

Unless long is 64-bit on your platform (which I assume is not, but
rather 32-bit), strtol() processes the full src[] and overflows.
According to K&R, page 252 LONG_MAX is returned, which is indeed
not equal to 0x12345678. Also errno is set to ERANGE.
Thx, that sounds interessting.
Not that I know of, using standard library functions. In that case you
must do it yourself. You could for example make a copy of the string
up to sizeof long bytes and pass that copy to strtol().
OK I will do something like this, when I need the value.

Thx
Peter
 
C

Case

Peter said:
Peter said:
Hi,

I will check a String which should contain a HEX value.
I know that strtol is the right function for this job.

But what happens when I will check a hex string with 8 bytes?
That I can check that the string is correct i know.

long value;
char src[]="0x1234567812345678"
char *err;
value = strtol(src,&err, 16);

Note that in this case (string starts with "0x") you could set
base to 0 and let strtol() figure it out. Just a remark; being
explicit is usually a good programming habit. :)

I know the possibility with 0, but the string should/must be a hex
value, if there is a possibilty to get the used base after strtol is
done, that will be create, but I don't think so.
I have written a big "if" with str[0] and str[1] to check a x X 0x 0X
at the beginning of the string and do then the strtol.

According to K&R x and X do not make the string hexadecimal. Only 0x or
0X are valid. So watch this! ---(What precisely do you want to catch
with this test? I means, is the 0x or 0X the only thing you expect to
go wrong possibly? Does this string come from user input?)---note
 
D

Dan Pop

In said:
I will check a String which should contain a HEX value.
I know that strtol is the right function for this job.

But what happens when I will check a hex string with 8 bytes?
That I can check that the string is correct i know.

long value;
char src[]="0x1234567812345678";
char *err;
value = strtol(src,&err, 16);
if (*err != 0x00)
return -1; /*FEHLER*/

The value is not 0x12345678 but I know it is right spelled.

Is that C89 standard or only on my compiler/OS (VC6, Windows) ?

It is C89, but your test is incorrect, as "0x1234567812345678" is of
the expected form in its entirety and there is no final string, so err
is guaranteed to point to the terminating null character:

fangorn:~/tmp 756> cat test.c
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <limits.h>

int main()
{
long value;
char src[]="0x1234567812345678";
char *err;

errno = 0;
value = strtol(src, &err, 16);
perror("strtol");
printf("%ld %ld\n", value, LONG_MAX);
printf("%d\n", *err);
return 0;
}
fangorn:~/tmp 757> gcc test.c
fangorn:~/tmp 758> ./a.out
strtol: Numerical result out of range
2147483647 2147483647
0

Which is exactly as documented: value is set to LONG_MAX, errno is set
to ERANGE and err points to the terminating null character. Of course,
the result would be different on a machine with 64-bit long's.

It is a real PITA to perform error checking correctly after a strtol
call:

errno = 0;
value = strtol(src, &err, 16);
if (err == src) /* complete garbage input */ ;
if (*err != 0) /* trailing garbage */ ;
if ((value == LONG_MAX || value == LONG_MIN) && errno == ERANGE)
/* overflow */;
/* value contains the result of a successful conversion */ ;

Depending on the application, the case of trailing garbage may not be
considered an error.
Is there a way to get the right value of the beginning of the string,
up to the sizeof(long) ?

Yes. The easy way is to insert a null character at the right place in
the input string. The hard way (when it is not guaranteed that the
input string can be modified) is to generate a sscanf format specifying
the maximum number of characters that should be converted and use it in
an sscanf call.

The hardest part is to compute the number of characters without
making *any* assumptions. sizeof(long) * 2 + 2 assumes an 8-bit byte
(and no padding bits). sizeof(long) * CHAR_BIT / 4 + 2 assumes a CHAR_BIT
that is a multiple of 4 and no padding bits in the representation. So,
you really have to start by "dissecting" LONG_MAX... And the easiest
way of doing it is:

char buff[sizeof(long) * CHAR_BIT / 3 + 2];
sprintf(buff, "%lx", (unsigned long)LONG_MAX);

Now, strlen(buff) + 2 is the bullet-proof solution to our problem.

The C99 snprintf removes the need for allocating buff, but reduces the
code portability (the SUS2 version of snprintf is useless for our purpose
and many C89 implementations don't provide snprintf at all).

Dan
 
P

Peter Dunker

According to K&R x and X do not make the string hexadecimal. Only 0x
or
0X are valid. So watch this!
very interessting.

---(What precisely do you want to catch
with this test? I means, is the 0x or 0X the only thing you expect to
go wrong possibly? Does this string come from user input?)---note
I read a XML Document, and will check that every numbered value is in a
special HEX format. If it is not, the user have to correct the
Document.
The correct Format is needed because I will save some information in my
own data format, and will link to the string(hex) inside the parser
implementation. So I don't need to copy all Data and out of my Program
I know that hex_string[2] up to the the NULL pointer is the hex value
in Bytes. (0x....)

Thx for your hints
Peter
 
S

Sam Dennis

Dan said:
It is a real PITA to perform error checking correctly after a strtol
call:
[...]
if ((value == LONG_MAX || value == LONG_MIN) && errno == ERANGE)
/* overflow */;

If my reading of the standard is correct, (errno == ERANGE) should
suffice for this error condition (although you'll normally want to
check whether it was too positive or too negative in the following
code), as this `use' of errno is documented; implementations might
set errno to some other non-zero value if there's no overflow, but
ERANGE seems to be reserved. (This reading is likely mere wishful
thinking; it seems far more likely that the intent is to prevent a
different value from being used under circumstances wherein one is
already prescribed.)
 
P

Peter Dunker

Sam Dennis said:
Dan said:
It is a real PITA to perform error checking correctly after a strtol
call:
[...]
if ((value == LONG_MAX || value == LONG_MIN) && errno == ERANGE)
/* overflow */;
If my reading of the standard is correct, (errno == ERANGE) should
suffice for this error condition (although you'll normally want to
check whether it was too positive or too negative in the following
code), as this `use' of errno is documented; implementations might
set errno to some other non-zero value if there's no overflow, but
ERANGE seems to be reserved. (This reading is likely mere wishful
thinking; it seems far more likely that the intent is to prevent a
different value from being used under circumstances wherein one is
already prescribed.)

THX

New Question, what is different between the || and | (&& and &)
I read anthing about that but I can't remember.
Is the if also correct if you use the & and | ?
 
D

Dan Pop

In said:
Dan said:
It is a real PITA to perform error checking correctly after a strtol
call:
[...]
if ((value == LONG_MAX || value == LONG_MIN) && errno == ERANGE)
/* overflow */;

If my reading of the standard is correct, (errno == ERANGE) should
suffice for this error condition (although you'll normally want to
check whether it was too positive or too negative in the following
code), as this `use' of errno is documented; implementations might
set errno to some other non-zero value if there's no overflow, but
ERANGE seems to be reserved. (This reading is likely mere wishful
thinking; it seems far more likely that the intent is to prevent a
different value from being used under circumstances wherein one is
already prescribed.)

If strtol is not returning LONG_MAX or LONG_MIN, what is preventing it
from setting errno to ERANGE?

The strtol usage of errno is documented *only* for the cases when
the return value is LONG_MAX or LONG_MIN.

The general rule is to ignore errno unless the function signals an error.

Dan
 
D

Dan Pop

In said:
New Question, what is different between the || and | (&& and &)
I read anthing about that but I can't remember.

Read again, until you can remember. It's a basic feature of the language.
Actually, it's trivial to remember, once you have *really* understood the
differences between them.
Is the if also correct if you use the & and | ?

In that particular case, yes. However, compare

if (x != 0 && 1.0 / x > FOO) ...

and

if (x != 0 & 1.0 / x > FOO) ...

and try to figure out which is correct and why.

Dan
 
P

Peter Nilsson

In said:
Dan said:
It is a real PITA to perform error checking correctly after a strtol
call:
[...]
if ((value == LONG_MAX || value == LONG_MIN) && errno == ERANGE)
/* overflow */;

If my reading of the standard is correct, (errno == ERANGE) should
suffice for this error condition (although you'll normally want to
check whether it was too positive or too negative in the following
code), as this `use' of errno is documented; implementations might
set errno to some other non-zero value if there's no overflow, but
ERANGE seems to be reserved. (This reading is likely mere wishful
thinking; it seems far more likely that the intent is to prevent a
different value from being used under circumstances wherein one is
already prescribed.)

If strtol is not returning LONG_MAX or LONG_MIN, what is preventing it
from setting errno to ERANGE?

7.5p3 ... The value of errno may be set to nonzero by a
library function call whether or not there is an error,
provided the use of errno is not documented in the
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
description of the function in this International Standard.
^^^^^^^^^^^^^^^^^^^^^^^^^^^
The strtol usage of errno is documented *only* for the cases when
the return value is LONG_MAX or LONG_MIN.

Hence, errno will only be set in that case.

What am I missing?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top