The standard C library functions strtof and strtod have the following signatures:
float strtof(const char *str, char **endptr);
double strtod(const char *str, char **endptr);
They each decompose the input string, str, into three parts:
- An initial, possibly-empty, sequence of whitespace
- A “subject sequence” of characters that represent a floating-point value
- A “trailing sequence” of characters that are unrecognized (and which do not affect the conversion).
If endptr is not NULL, then *endptr is set to a pointer to the character immediately following the last character that was part of the conversion (in other words, the start of the trailing sequence).
I am wondering: why is endptr, then, a pointer to a non-const char pointer? Isn’t *endptr a pointer into a const char string (the input string str)?
The reason is simply usability.
char *can automatically convert toconst char *, butchar **cannot automatically convert toconst char **, and the actual type of the pointer (whose address gets passed) used by the calling function is much more likely to bechar *thanconst char *. The reason this automatic conversion is not possible is that there is a non-obvious way it can be used to remove theconstqualification through several steps, where each step looks perfectly valid and correct in and of itself. Steve Jessop has provided an example in the comments:A much better approach would have been to define these functions to take(The stricken text was actually a very bad idea; not only does it prevent any type checking, but C actually forbids objects of typevoid *in place ofchar **. Bothchar **andconst char **can automatically convert tovoid *.char *andconst char *to alias.) Alternatively, these functions could have taken aptrdiff_t *orsize_t *argument in which to store the offset of the end, rather than a pointer to it. This is often more useful anyway.If you like the latter approach, feel free to write such a wrapper around the standard library functions and call your wrapper, so as to keep the rest of your code
const-clean and cast-free.