atoi return

B

Bill Cunningham

I have just read atoi() returns no errors. It returns an int though and
the value of the int is supposed to be the value of the conversion. It seems
to me that right there tells you if there was success or not. Am I wrong?

Bill
 
I

Ian Collins

Bill said:
I have just read atoi() returns no errors. It returns an int though and
the value of the int is supposed to be the value of the conversion. It seems
to me that right there tells you if there was success or not. Am I wrong?
Wasn't this all beaten to death on one of your threads a week or two back?

What value would indicate failure?
 
R

Richard

Bill Cunningham said:
I have just read atoi() returns no errors. It returns an int though and
the value of the int is supposed to be the value of the conversion. It seems
to me that right there tells you if there was success or not. Am I wrong?

Bill

What you should do is use sprintf and scanf and then do a string compare
with their output to your atoi output. If the result is the same then
you are on the right track.
 
I

Ian Collins

Richard said:
What you should do is use sprintf and scanf and then do a string compare
with their output to your atoi output. If the result is the same then
you are on the right track.
Are you baiting pool Bill, or posting bollocks?
 
K

Keith Thompson

Bill Cunningham said:
I have just read atoi() returns no errors. It returns an int though and
the value of the int is supposed to be the value of the conversion. It seems
to me that right there tells you if there was success or not. Am I wrong?

Yes.

Take a look at the following program and tell me how you'd detect an
error in a call to atoi().

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *good = "0";
char *bad = "bad";
printf("atoi(\"%s\") = %d\n", good, atoi(good));
printf("atoi(\"%s\") = %d\n", bad, atoi(bad));
return 0;
}
 
B

Bill Cunningham

Yes.

Take a look at the following program and tell me how you'd detect an
error in a call to atoi().

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *good = "0";
char *bad = "bad";
printf("atoi(\"%s\") = %d\n", good, atoi(good));
printf("atoi(\"%s\") = %d\n", bad, atoi(bad));
return 0;
}

I can't really read that Keith but if I remember right this was
mentioned before but never really explained. I would've tried something
like this if it's even valid.
....
int i;
if (i=atoi(argv[1]))!=sizeof(int))
fprintf(stderr,"error\n");

*sigh* I dunno. Does this make any sense?

Bill
 
K

Keith Thompson

Bill Cunningham said:
Keith Thompson said:
Take a look at the following program and tell me how you'd detect an
error in a call to atoi().

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *good = "0";
char *bad = "bad";
printf("atoi(\"%s\") = %d\n", good, atoi(good));
printf("atoi(\"%s\") = %d\n", bad, atoi(bad));
return 0;
}

I can't really read that Keith but if I remember right this was
mentioned before but never really explained. I would've tried something
like this if it's even valid.
...
int i;
if (i=atoi(argv[1]))!=sizeof(int))
fprintf(stderr,"error\n");

*sigh* I dunno. Does this make any sense?

No, it doesn't. What does sizeof(int) have to do with anything?

Yes, this was mentioned before, and it was explained in great detail.

Here's the point. If you give atoi() a string that doesn't represent
a number, such as the string "bad", it returns 0. If you give it the
string "0", which does represent a number it returns 0. If atoi()
returns 0, you *can't tell* whether it successfully converted the
string "0" or failed to convert the string "bad".

Even worse, if atoi() is given a string that represents a number
that's too big to hold in an int, it invokes undefined behavior. For
example, there's no telling what atoi("99999999999999999999") will do;
it could crash your program or worse.
 
B

Bill Cunningham

[snip]
Here's the point. If you give atoi() a string that doesn't represent
a number, such as the string "bad", it returns 0. If you give it the
string "0", which does represent a number it returns 0. If atoi()
returns 0, you *can't tell* whether it successfully converted the
string "0" or failed to convert the string "bad".

Even worse, if atoi() is given a string that represents a number
that's too big to hold in an int, it invokes undefined behavior. For
example, there's no telling what atoi("99999999999999999999") will do;
it could crash your program or worse.

I see. Must be a left over dinosaur like gets().

Bill
 
K

Keith Thompson

Bill Cunningham said:
[snip]
Here's the point. If you give atoi() a string that doesn't represent
a number, such as the string "bad", it returns 0. If you give it the
string "0", which does represent a number it returns 0. If atoi()
returns 0, you *can't tell* whether it successfully converted the
string "0" or failed to convert the string "bad".

Even worse, if atoi() is given a string that represents a number
that's too big to hold in an int, it invokes undefined behavior. For
example, there's no telling what atoi("99999999999999999999") will do;
it could crash your program or worse.

I see. Must be a left over dinosaur like gets().

Pretty much. It's not nearly as dangerous as gets, though; since its
behavior depends on the argument you pass to it (which you can check),
not on what appears on stdin (over which you typically have no
control), it *can* be used safely. But by the time you add code to
verify the argument before calling atoi(), you might as well call
strtol().
 
C

CBFalconer

Bill said:
.... snip ...


I see. Must be a left over dinosaur like gets().

No. gets() is just unsafe regardless. atoi() can be used safely,
but why bother when you have strtol available.
 
C

CBFalconer

Richard said:
CBFalconer said:

In other words, it's a left over dinosaur. And so is gets().
Therefore, it's a left over dinosaur like gets(). Which is what he
said.

Not so. gets should never appear in any code. atoi can. One
objective of the C standard is to preserve the viability of old
code.

I can also see various other differences between gets and atoi. So
the above comment is simply a waste of time.
 
V

vippstar

Not so. gets should never appear in any code. atoi can. One
objective of the C standard is to preserve the viability of old
code.

gets(stdout); is safe I believe, just like atoi("123"); is safe.
 
J

James Kuyper

gets(stdout); is safe I believe, just like atoi("123"); is safe.

You might want to rethink that assertion - recheck the interface for gets().

The function that allows you to specify the file handle is fgets(), not
gets(), and it is possible to use it safely, because it also takes an
length argument for the buffer. However, using it on stdout seems, at
best, problematic, since stdout is defined as an output stream.

I suspect that you mean something substantially different from what you
wrote.
 
V

vippstar

(e-mail address removed) wrote:

...


You might want to rethink that assertion - recheck the interface for gets().

The function that allows you to specify the file handle is fgets(), not
gets(), and it is possible to use it safely, because it also takes an
length argument for the buffer. However, using it on stdout seems, at
best, problematic, since stdout is defined as an output stream.

I suspect that you mean something substantially different from what you
wrote.

Yes. I tried to find what the standard says about input operations on
output streams, but failed.
I had forgotten how gets works!


#include <stdio.h>
#include <stdlib.h>

int main(void) {
char c;

if(freopen(tmpnam(NULL), "r", stdin) == NULL) exit(EXIT_FAILURE);
gets(&c);
return 0;
}
 
N

Nate Eldredge

Yes. I tried to find what the standard says about input operations on
output streams, but failed.
I had forgotten how gets works!


#include <stdio.h>
#include <stdlib.h>

int main(void) {
char c;

if(freopen(tmpnam(NULL), "r", stdin) == NULL) exit(EXIT_FAILURE);
gets(&c);
return 0;
}

Still no good; another process could write 2 bytes to your temporary
file after it's opened but before your gets() call runs. (Provided, of
course, your system has other processes, or some equivalent notion.)

On a Unix system, you could create a pipe, write into one end, and use
gets() on the other (via fdopen()). That would be safe because the pipe
isn't visible to anyone else. Or you could open /dev/null. But I don't
think there's a way in portable C to have a FILE that only your program
can write to, so there isn't any safe way to use gets().
 
V

vippstar

Still no good; another process could write 2 bytes to your temporary
file after it's opened but before your gets() call runs. (Provided, of
course, your system has other processes, or some equivalent notion.)

Whoops, I meant "w" there, to demonstrate it's not possible to read
from a write-only file.
SORRY for this! :-(
 
C

CBFalconer

gets(stdout); is safe I believe, just like atoi("123"); is safe.

No, gets is never safe. Read the literature, or scan the c.l.c
archives. atoi is always safe if you limit the input string to
length 4, or even more according to the value of INT_MAX.
 
C

CBFalconer

Richard said:
CBFalconer said:

Yes, of course there are differences. Here's another for you - gets
is intended to accept a string of data from the user, whereas atoi
is intended to convert a string value into an int value. Nobody is
claiming the two functions are identical, you berk. The claim was
that they shared a characteristic - i.e. that they were left-over
dinosaurs.


In future, *please* think before replying - or, indeed, instead.

I fail to appreciate why you wish to waste time on this inaccurate
foolishness. I do not find any definition of 'left over dinosaur'
in the C standard.
 
K

Keith Thompson

Richard Heathfield said:
CBFalconer said:



Rubbish. Even a length of 1 isn't guaranteed to be safe. The behaviour of
atoi("X") is undefined.
[...]

I'm not quite sure about that. Here's what the C99 standard says:

The functions atof, atoi, atol, and atoll need not affect the
value of the integer expression errno on an error. If the value
of the result cannot be represented, the behavior is undefined.

...

The atoi, atol, and atoll functions convert the initial portion of
the string pointed to by nptr to int, long int, and long long int
representation, respectively. Except for the behavior on error,
they are equivalent to

atoi: (int)strtol(nptr, (char **)NULL, 10)

Certainly the behavior of atoi("99999999999999999999") is undefined
(assuming 99999999999999999999 exceeds INT_MAX). But
strtol("X", NULL, 10) returns 0 and sets errno to ERANGE.

One reasonable interpretation of the standard's wording is that the
behavior of atoi() on error (either an out-of-range argument or a
conversion failure) is undefined. Another reasonable interpretation,
I think, is that atoi("X") returns 0 and doesn't necessarily set
errno.

It would have been nice if the standard had simply required atoi() to
be equivalent to (int)strtol(nptr, (char **)NULL, 10).
 
K

Keith Thompson

Keith Thompson said:
The behaviour of atoi("X") is undefined.
[...]

I'm not quite sure about that. Here's what the C99 standard says:

The functions atof, atoi, atol, and atoll need not affect the
value of the integer expression errno on an error. If the value
of the result cannot be represented, the behavior is undefined.

...

The atoi, atol, and atoll functions convert the initial portion of
the string pointed to by nptr to int, long int, and long long int
representation, respectively. Except for the behavior on error,
they are equivalent to

atoi: (int)strtol(nptr, (char **)NULL, 10)

Certainly the behavior of atoi("99999999999999999999") is undefined
(assuming 99999999999999999999 exceeds INT_MAX). But
strtol("X", NULL, 10) returns 0 and sets errno to ERANGE.

One reasonable interpretation of the standard's wording is that the
behavior of atoi() on error (either an out-of-range argument or a
conversion failure) is undefined. Another reasonable interpretation,
I think, is that atoi("X") returns 0 and doesn't necessarily set
errno.

A quick search of Google's comp.std.c archives tends to support the
idea that atoi("X") is well-defined and must return 0. The behavior
of atoi() is equivalent to that of strtol() *except on an error*.
strtol() with a first argument of "X" doesn't set errno, which tends
to imply that it isn't considered an error. Therefore, atoi("X") is
equivalent to strtol("X", NULL, 10), which returns 0.

I'd be more comfortable if the standard stated this more clearly.
 

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

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top