自分はほんの駆け出しですが…
まずは、下記をを復習してみてください。理解の助けになります。
文字列をポインタで操作する方法(こちらを参照)
関数から文字列を返す方法(こちらを参照)
その上で、私なりの説明を試みてみます。
-
文字列操作関数「str_copy」は、{第一引数}←{第二引数} に文字列をコピーするもの
-
関数呼び出し時に与えられる「実引数」は文字型配列の名前「s2」「s1」で、文字列の先頭アドレスを示す
-
関数 str_copy が受け取る「仮引数」は文字列型へのポインタ型
-
関数が呼び出された直後は、「d」「s」ともに受け取った文字列の先頭アドレスを示す
-
第二引数は「コピー元」(=変更されることはない)なので、「const」として定義されている
-
「while(*d++ =*s++) ;」の部分は、下記3種類のことを1行で実施(→補足1)
①先頭から1文字ずつ、②文字列の末尾まで、③コピーする
-
「char *t=d;」はコピー結果を返すための準備(→補足2)
補足1)while
文の意味するところ
while( {繰り返し条件} )
; ← 普通はここに処理したいコマンドのフロック {〜} が来るが、ここでは何もしない
従って、すべての処理は繰り返し条件の部分に記載された「*d++ =*s++」という式で実行される訳ですが、以下のように分けて考えると分かりやすいです。
-
ループの1回目では、第二引数の1文字目(*s++)が第一引数の1文字目(*d++)にコピー(=代入)される
-
コピーが完了した時点で各ポインタの値がインクリメント(++)され、次の文字をコピーする「準備」をしている
-
上記が完了した時点で、{繰り返し条件} の「式全体の評価は、コピーされた「文字コード」(≠0)なので、ループ処理を終えずに2週目を実行する
-
もし処理が進んで文字列の「終端」に到達すると、コピーされる文字コードは「終端記号」(=\0)で式全体の評価はゼロとなり、繰り返し条件が「false」となって処理を終える
補足2)return(t);
は実際のところ 何
を返しているのか?
関数「str_copy」の引数は文字型配列(=配列の先頭アドレス)を受け取っている(=参照渡し)ので、文字列のコピー結果は、呼び出し元の文字型配列「s2」に直接反映されます。
しかし、「関数」である以上、関数の戻り値としてもコピー結果を受け取りたいです。
そこで、実際のコピー処理を開始する前に「準備」として char *t=d;
としておくと、第一引数(コピー先)である文字型配列「s2」の先頭アドレス(ポインタ)を、文字列型ポインタ変数「t」に保存しておけます。
この変数「t」は通常の文字列型ポインタ変数であって、決してポインタのポインタではありません。
もしポインタのポインタを宣言したい場合は char **t
のように *
を重ねます。実際には使用されることはありませんが、「((ポインタのポインタ)のポインタ)の…」というように多重間接参照ということも可能です。(参考)
なぜコピー処理の前にこんなことをしているか?というと、文字列を1文字ずつコピーする際に、変数「d」の値はインクリメントされていまう(コピー完了後は、もはや文字列の先頭を示していない)からです。
要するに、この関数は、文字列のコピー結果を呼び出し元の「コピー先配列:s2」へ直に反映させると共に、コピー先文字列の先頭アドレスを「関数の戻り値」としても返却しています。
このように、文字列など複数の値を関数の戻り値として返したい場合には、ポインタ型を使用するのが 常套手段 となっています。(参考)
なので、この関数は char *str_copy
というように文字列型へのポインタ型として定義されています。
このように文章だけで説明しようとするとどうしても長くてややこしくなってしまうのですが、少しでも理解の助けになれば幸いです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。