strtol clarification

K

Kristo

Since there's no strtoi function in standard C, I've been searching the
clc archives for the proper way to store the result of strtol to an
int. My search has yielded conflicting results. About half of the
results say to cast the result to an int. The other half say the cast
isn't necessary. And the third half say to compare the result to
INT_MAX and INT_MIN before assigning. Which is correct?

Kristo
 
C

Chris Croughton

Since there's no strtoi function in standard C, I've been searching the
clc archives for the proper way to store the result of strtol to an
int. My search has yielded conflicting results. About half of the
results say to cast the result to an int. The other half say the cast
isn't necessary. And the third half say to compare the result to
INT_MAX and INT_MIN before assigning. Which is correct?

Yes. Or no.

Personally, I don't use an explicit cast unless the compiler I'm forced
to use produces warnings about loss of precision (in that case the
explicit cast says "yes, I intend to lose precision here"; I'd prefer
to turn the warning off but company policy says otherwise).

Doing the comparison with INT_MAX and INT_MIN is useful if you can take
appropriate action on failure and especially if the truncated result
will result in errors. However, it's more likely that the test should
be on the range of expected values, not on some implementation-defined
size of an int (i.e. the problem domain not the target implementation
domain -- if you can validly receive "32768" as an input but you only
have 16 bit signed int variables then it's a programming error not an
input error).

Chris C
 
L

Lawrence Kirby

Since there's no strtoi function in standard C, I've been searching the
clc archives for the proper way to store the result of strtol to an
int. My search has yielded conflicting results. About half of the
results say to cast the result to an int. The other half say the cast
isn't necessary. And the third half say to compare the result to
INT_MAX and INT_MIN before assigning. Which is correct?

C will convert implicitly between int and long so the cast is not
necessary. Some compilers might decide to complain about a shortening
conversion since there is a risk of undefined behaviour - compilers can
complain about anything they like. The cast MAY eliminate such a
diagnostic. For correctness, yes, check the long value is in the range of
INT_MIN to INT_MAX before converting to int. If it isn't then you get the
undefined behaviour mentioned.

So casting/not casting makes no difference functionally, bounds checking
is necessary for correctness.

Lawrence
 
E

Emmanuel Delahaye

Kristo wrote on 08/04/05 :
Since there's no strtoi function in standard C, I've been searching the
clc archives for the proper way to store the result of strtol to an
int. My search has yielded conflicting results. About half of the
results say to cast the result to an int. The other half say the cast
isn't necessary. And the third half say to compare the result to

3 halves ?

"Fascinating" -- Dr Spock
INT_MAX and INT_MIN before assigning. Which is correct?

The latter.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"There are 10 types of people in the world today;
those that understand binary, and those that dont."
 
K

Kristo

[snip details]
So casting/not casting makes no difference functionally, bounds
checking is necessary for correctness.

Ok thanks for clearing that up. Looks like it'll be worth my while to
write StrToInt and StrToUint to do the bounds checking.

<OT>
Do you happen to know if most (any) compilers provide strtoi and
strtoui as an extension?
</OT>

Kristo
 
C

CBFalconer

Kristo said:
Since there's no strtoi function in standard C, I've been searching
the clc archives for the proper way to store the result of strtol
to an int. My search has yielded conflicting results. About half
of the results say to cast the result to an int. The other half
say the cast isn't necessary. And the third half say to compare
the result to INT_MAX and INT_MIN before assigning. Which is
correct?

Try applying some elementary reasoning to the problem. Under what
circumstances can the value stored in a long be stored in an int?
Do those circumstances depend on the actual value in that long? If
so, how does one check that they are suitable for an int?

Any time you see a cast, the code is very likely to be wrong.
 
K

Keith Thompson

Lawrence Kirby said:
C will convert implicitly between int and long so the cast is not
necessary. Some compilers might decide to complain about a shortening
conversion since there is a risk of undefined behaviour - compilers can
complain about anything they like. The cast MAY eliminate such a
diagnostic. For correctness, yes, check the long value is in the range of
INT_MIN to INT_MAX before converting to int. If it isn't then you get the
undefined behaviour mentioned.

Not quite. Converting a value from long to int leaves the value
unchanged if it can be represented as an int; otherwise (on overflow),
it either yields an implementation-defined result or raises an
implementation-defined signal (C99 6.3.1.3). C90 says the result is
implementation-defined; there's no mention of raising a signal (C90
6.2.1.2).
 
K

Keith Thompson

Emmanuel Delahaye said:
"Fascinating" -- Dr Spock

<WAY_OT>
Dr. Benjamin Spock may well have said "Fascinating" some time in his
life, but you're probably thinking of Mr. Spock (who has the equivalent
of several doctorate degrees, but is never referred to as "Doctor").
</WAY_OT>
 
A

Andrey Tarasevich

Kristo said:
Since there's no strtoi function in standard C, I've been searching the
clc archives for the proper way to store the result of strtol to an
int. My search has yielded conflicting results. About half of the
results say to cast the result to an int. The other half say the cast
isn't necessary. And the third half say to compare the result to
INT_MAX and INT_MIN before assigning. Which is correct?
...

The latter is correct, meaning that you should to store the immediate
result in a 'long' object, check the range and then convert the result
(explicitly or implicitly) to the final 'int' value.

Note that it is also necessary to make sure that 'strtol' actually
succeeded, i.e., among other things, that the source representation
actually fits into a 'long' after conversion. If it doesn't, 'strtol'
returns 'LONG_MIN' or 'LONG_MAX'. If on your platform the range of
'long' is greater than that of 'int' (i.e. LONG_MIN < INT_MIN and
LONG_MAX > INT_MAX) then this check will be "automatically" included
into the aforementioned 'int'-range check. Otherwise, if the range of
'long' is the same as that of 'int', you'll have to do a separate check
by analyzing 'errno' value: 'strtol' will set 'errno' to 'ERANGE' in
"out of 'long' range" situations.

Of course, for portability reasons, it makes more sense to always follow
the latter approach, i.e. check the 'errno'.
 
W

William Ahern

Kristo said:
[snip details]
So casting/not casting makes no difference functionally, bounds
checking is necessary for correctness.

Ok thanks for clearing that up. Looks like it'll be worth my while to
write StrToInt and StrToUint to do the bounds checking.

Or use OpenBSD's strtonum(), which has shipped since 3.5 or 3.6. It's
actually meant as a replacement for atoi().

long long
strtonum(const char *nptr, long long minval, long long maxval,
const char **errstr);

http://www.openbsd.org/cgi-bin/man.cgi?query=strtonum.

http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdlib/strtonum.c

It's quite simple to use:

const char *errstr;
int i = strtonum(numstr,INT_MIN,INT_MAX,&errstr);

if (errstr)
/* fail gracefully */

/* continue */
 
R

Richard Bos

Keith Thompson said:
<WAY_OT>
Dr. Benjamin Spock may well have said "Fascinating" some time in his
life, but you're probably thinking of Mr. Spock (who has the equivalent
of several doctorate degrees, but is never referred to as "Doctor").
</WAY_OT>

"I'm a science officer, Jim, not a doctor."

Richard
 
M

Michael Wojcik

Any time you see a cast, the code is very likely to be wrong.

Trivial counterexample: casting plain char to unsigned char when using
the functions from <ctype.h>. Suppressing unnecessary diagnostics,
as in the very situation described in this thread (after proper range
checking), is another.

Casts often indicate wrong, or at least infelicitous, code, but "any
time" and "very likely" are too strong.

--
Michael Wojcik (e-mail address removed)

I will shoue the world one of the grate Wonders of the world in 15
months if Now man mourders me in Dors or out Dors
-- "Lord" Timothy Dexter, _A Pickle for the Knowing Ones_
 
M

Mark McIntyre

Trivial counterexample: casting plain char to unsigned char when using
the functions from <ctype.h>.

This is /not/ a counterexample in any shape or form. Re-read CBF's
post, and see if the clause "very likely to be" helps.
 
K

Keith Thompson

Mark McIntyre said:
This is /not/ a counterexample in any shape or form. Re-read CBF's
post, and see if the clause "very likely to be" helps.

Can we not have yet another argument about the way a statement was
phrased?

It's arguably true that most casts are very likely to be wrong. Some
casts are valid, but it's possible that there are more useless casts
in real-world code than useful ones. I have no idea what the actual
numbers are; possibly the bulk of C code is better than I suspect it
is.

On the other hand, CBFalconer's statement could be interpreted to mean
that *any* given cast is very likely to be wrong, which is not true
since there are casts that are not "very likely to be wrong". I don't
believe that's what he meant, since he knows better. He could have
worded it better.

I presume we all agree that some casts (including Michael Wojcik's
example) are valid, and some other casts (such as casting the result
of malloc() are legal but "very likely to be wrong".
 
M

Michael Wojcik

This is /not/ a counterexample in any shape or form. Re-read CBF's
post, and see if the clause "very likely to be" helps.

A swing and a miss, Mark.

Since I can read my own source code, I can see the casts I employ
when passing plain char arguments to ctype.h functions. Thus they
are instances of "any time see a cast".

They are all correct; thus there is zero likelihood that the code
is wrong.

Thus this is a counterexample to Falconer's post, in precisely the
shape and form that I originally posted it. The adverbial phrase
(it's not the complete clause) "very likely to be", of which I was
perfectly cognizent when I composed my previous post, does not alter
that a whit.

Thanks for playing.

--
Michael Wojcik (e-mail address removed)

This year's runner-up in the All-Usenet Creative Use Of English In A
Quasi-Legal But Probably Completely Ineffectual Signature Statement:

Disclaimer : I am a free denizen of this world and statements are of mine
and solly mine. Nobody dare sue me as you may end up even loosing your
attorney fees. -- Sridhar ([email protected])
 

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
474,161
Messages
2,570,892
Members
47,431
Latest member
ElyseG3173

Latest Threads

Top