Проблема с вашим первым кодом заключается в том, что tmp
указывает на строковый литерал, который доступен только для чтения. Когда strtok
пытается изменить строку, происходит сбой.
Проблема с вашим вторым кодом отсутствует:
#include <string.h>
Отсутствующий заголовок означает, что strtok
не объявлено в вашей программе. Компилятор C предполагает, что все необъявленные функции возвращают int
. Это не верно для strtok
, который возвращает char *
. Вероятная причина сбоя в вашем примере заключается в том, что код работает на 64-разрядной машине, где указатели имеют ширину 8 байт, а int
- всего 4 байта. Это портит возвращаемое значение strtok
, поэтому first
является указателем мусора (и printf
падает, когда пытается его использовать).
Вы можете подтвердить это сами, выполнив
char *first = strtok(tmp, ".");
printf("%p %p\n", (void *)tmp, (void *)first);
Адреса, напечатанные для tmp
и first
, должны быть идентичными (и если вы #include <string.h>
).
Самое смешное, что gcc может предупредить вас об этих проблемах:
main.c: In function 'main':
main.c:6:19: warning: implicit declaration of function 'strtok' [-Wimplicit-function-declaration]
char *first = strtok(tmp, ".");
^
main.c:6:19: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
main.c:7:20: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
char *second = strtok(tmp, "."); // Yes, should be NULL
^
... и onlinegdb покажет вам эти предупреждения, но только в случае сбоя компиляции!
Чтобы увидеть предупреждения компилятора в onlinegdb, вам нужно добавить в код серьезную ошибку (например, поставив @
в последней строке файла).