質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.62%

  • C

    3558questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ポインタを指すポインタ?

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 612

reotantan

score 245

char *t=d;の部分なのですが、
d自体がs2配列の先頭アドレスを示すポインタなので、
tはポインタのアドレスを示しているポインタという事ですか?
あとwhile(*d++ =*s++)
      ;というのは
()の式を評価して1になる間は()の
中の命令を続けるという事ですよね?
詳しいかた、教えてください
char *str_copy(char *d,const char *s)
{

  char *t=d;

  while(*d++ =*s++)
      ;
  return(t);
}


int main (void)
{

  char s1[128]="ABCD";
  char s2[128]="EFGH";

  printf("s1:" );
  scanf("%s",s1 );


  str_copy(s2,s1);

  puts("copied s1 ");
  printf("s1=%s\n",s1 );
  printf("s2=%s\n",s2 );

return 0;
}
コード
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

ポインタのポインタだったら
char**です。

質問文のコードは
char str[]="ABC";
char* d;
char* t;
t = d;
...

こんな感じです


C言語は真偽を「0だったら偽、それ以外は正」とします。
while(*d++=*s++)
*dに*sを代入して代入した値が0じゃなければまた繰り返す。
で、後置インクリメントつきなので操作の後にdとsをchar1つ分進める処理も入ってます。

「"ABC"のどこに0があるんだよ」と思うかもしれませんが、
"ABC"というのは{'A' , 'B' , 'C' , 0}と同等です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/05 00:23

    そういう事ですか、ただchar型を入れられるポインタとして宣言しただけだったんですね。
    ありがとうございます

    キャンセル

+1

自分はほんの駆け出しですが…

まずは、下記をを復習してみてください。理解の助けになります。
文字列をポインタで操作する方法(こちらを参照)
関数から文字列を返す方法(こちらを参照)

その上で、私なりの説明を試みてみます。

  • 文字列操作関数「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 というように文字列型へのポインタ型として定義されています。

このように文章だけで説明しようとするとどうしても長くてややこしくなってしまうのですが、少しでも理解の助けになれば幸いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

おそらく、このstr_cpy()関数の仕様として、戻り値の値はコピー先の先頭アドレスを返すという仕様なのでしょう。そのため、dの値を退避しています。
#tは処理されず、戻り値としてしか使用されていませんよね。
アドレスを扱うため、ポインタ変数として宣言する必要があります。

whileループですが、考え方はその通りです。sの内容を一字ずつdへコピーするためのループです。
で、終了条件ですが、文字列なので、最後はNULL文字になります。NULL文字は文字コードが0のデータであるため、NULL文字をコピーしたと同時にループ条件が終了(0なので、条件が「偽」となり、ループを抜ける)となります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/09/05 00:23

    解説ありがとうございます、とても理解に役立ちました

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.62%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C

    3558questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。