The following code runs well under gcc 11.2.1:
// test.c
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv){
char *msg;
unsigned int val;
msg = "1024 2048 4096 13";
while(*msg != '\0'){
val = strtoul(msg, &msg, 10);
printf("%u\n",val);
}
return 0;
}
gcc -Wall -o test.bin test.c
$ ./test.bin
1024
2048
4096
13
Regarding the function strtoul
,
unsigned long int strtoul(const char *str, char **endptr, int base)
(See notes on Update below.)
Is it correct to pass references to the same object in str
and endptr
? Or is it just a lucky coincidence that it did not explode in my face?
The reference manuals to stdlib
do not mention that (for example).
strtoul
function is called nptr
as opposed to str
which is the name used in this question. The answer and discussion below mostly uses nptr
.restrict
.strtoul()
Other than the restrict
qualifiers, neither the documentation for strtoul
, in C 2018 7.22.1.4, nor the documentation for using the standard library generally, in 7.1.4, state any prohibition on *endptr
pointing to the same memory that nptr
does (where endptr
and nptr
are the second and first arguments of strtoul
, respectively), nor do they state any relaxation of the specification under this condition (for example, there is no assertion that the behavior would be undefined if such a condition holds).
So we just need to consider the restrict
qualifiers. strtoul
is declared as unsigned long int strtoul(const char * restrict nptr, char ** restrict endptr, int base)
. Using the formal definition of restrict
in 6.7.3.1 and considering the restrict
on nptr
first, 6.7.3.1 4 tells us that, if the memory pointed to by nptr
or any is modified by any means, then every other lvalue used to access it shall be based on nptr
. This condition is satisfied because strtoul
will not modify the string that nptr
points to.
Considering the restrict
on endptr
, we observe the memory it points to is indeed modified, as strtoul
stores a value to that memory. Then 6.7.3.1 4 requires that every other lvalue used to access that memory shall be based on endptr
. This condition is satisfied because strtoul
does not access the bytes representing msg
other than through endptr
.
Therefore, the routine should function as specified in 7.22.1.4 even if it is called with strtoul(msg, &msg, 10)
.