It seems that strtol()
and strtod()
effectively allow (and force) you to cast away constness in a string:
#include <stdlib.h>
#include <stdio.h>
int main() {
const char *foo = "Hello, world!";
char *bar;
strtol(foo, &bar, 10); // or strtod(foo, &bar);
printf("%d\n", foo == bar); // prints "1"! they're equal
*bar = 'X'; // segmentation fault
return 0;
}
Above, I did not perform any casts myself. However, strtol()
basically cast my const char *
into a char *
for me, without any warnings or anything. (In fact, it wouldn't allow you to type bar
as a const char *
, and so forces the unsafe change in type.) Isn't that really dangerous?
To determine if 0 is valid, you must also look at the value errno was set do during the call (if it was set). Specifically, if errno != 0 and the value returned by strtol is 0 , then the value returned by strtol is INVALID.
* The atoi function is not thread-safe and also not async-cancel safe. * The atoi function has been deprecated by strtol and should not be used in new code.
Nowhere does the strtol doc say anything about allocating memory; it quite clearly says that the endptr (not error) is set to point to the char that wasn't parsed. And if it did allocate memory, you would be leaking it, as you only do the free outside the loop.
strtol() (and its family) is the safest standard one and also a very fast one, but it is incredibly difficult to use, so I decided to write a safe and simple interface to it.
I would guess that because the alternative was worse. Suppose the prototype were changed to add const
:
long int strtol(const char *nptr, const char **endptr, int base);
Now, suppose we want to parse a non-constant string:
char str[] = "12345xyz"; // non-const
char *endptr;
lont result = strtol(str, &endptr, 10);
*endptr = '_';
printf("%s\n", str); // expected output: 12345_yz
But what happens when we try to compile this code? A compiler error! It's rather non-intuitive, but you can't implicitly convert a char **
to a const char **
. See the C++ FAQ Lite for a detailed explanation of why. It's technically talking about C++ there, but the arguments are equally valid for C. In C/C++, you're only allowed to implicitly convert from "pointer to type" to "pointer to const
type" at the highest level: the conversion you can perform is from char **
to char * const *
, or equivalently from "pointer to (pointer to char
)" to "pointer to (const
pointer to char
)".
Since I would guess that parsing a non-constant string is far more likely than parsing a constant string, I would go on to postulate that const
-incorrectness for the unlikely case is preferable to making the common case a compiler error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With