質問: strtok(NULL, ",;"); printf("%s\n", ptr); return(0); } ||< 最初のコードで「セグメンテーション違反」が出た理由は何でしょうか? それらを説明してくれているサイトなど、参考になるものを教えていただけると幸です。 OS: Vine Linux 6.2 gccバージョン: 4.4.5 よろしくお願いします。
回答: これが原因です。 > これらの関数はその最初の引数を変更する。 > > Man page of STRTOK C 言語での文字列リテラルは、コンパイラの実装に任されてはいますが、変更不能な領域に配置されることが多いです。 strtok() は、呼び出すたびに、最初の呼び出しで指定された文字列の中身を書き換えます。 質問の前半のコードでは、文字列リテラルの中身を書き換えているので、Segmentation Fault が発生します。 後半のコードでは、auto な char の配列の内容を書き換えているので、書き換えは許されており、Segmentation Fault は発生しません。 ``` strcpy( chk, "abc,def;ghi"); ptr = strtok(chk, ",;"); ``` を行うと、配列 chk に格納されている "abc" の後に続く "," が \0 に書き換えられています。 strtok() が返しているのは、実は chk の先頭アドレスです。 カンマが \0 に書き換えられているので、strtok() が返すポインタを printf で表示すると "abc" の後に続く \0 までが表示されるので、"abc" と表示されます。 同様に、次の、 ``` ptr = strtok(NULL, ",;"); ``` では、"def" に続く ";" が \0 に書き換えられて、'd' が格納されている位置を strtok() が返します。 この挙動は、コンパイラによって違ってきます。 今では、ほとんど触れることはできなくなっていますが、MS-DOS の環境や、組み込み系の環境だと、文字列リテラルの内容を書き換えても、許されることがあります。