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

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

ただいまの
回答率

90.61%

  • C++

    3341questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

このコードがなぜ動くのか教えてほしいです

解決済

回答 1

投稿

  • 評価
  • クリップ 2
  • VIEW 489

Lopn_

score 36

#include <iostream>

int main() {
    std::string s("Hello World!");
    char *p[15] = {(char*)s.c_str()};

    for (int i = 1; i < 15; i++) {
        p[i] = {(char*)&p[i - 1]};
    }

    std::cout << **************(char***************)p[14] << std::endl;;

    getchar();
    return 0;
}
char *p[15] = {(char*)s.c_str()};

の部分はstring型をchar arrayに変換しているということなのでしょうか?

それと、

#include <iostream>

int main() {
    std::string s("Hello World!");
    char *p[2] = {(char*)s.c_str()};

    for (int i = 1; i < 2; i++) {
        p[i] = {(char*)&p[i - 1]};
    }

    std::cout << *(char**)p[1] << std::endl;;

    getchar();
    return 0;
}

でも同じ結果が得られるのですがなぜでしょうか??

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+2

char *p[15] = {(char*)s.c_str()};

char *p[15];
p[0] = (char*)s.c_str();
p[1] = 0;
p[2] = 0;
...
p[14] = 0;

と等価です。
つまり"Hello World!"の先頭アドレスをp[0]が保持しているだけです。

次のループでは、
p[1]にp[0]のアドレスを入れ、
p[2]にp[1]のアドレスを入れ、
...
p[14]にp[13]のアドレスを入れています。

ということは、
p[14]が保持している値は変数p[13]のアドレス
p[13]が保持している値は変数p[12]のアドレス
...
p[1]が保持している値は変数p[0]のアドレス
ということになります。

ポインタ変数は*を付けると保持しているアドレスが指し示す先の値を意味しますので、
(*p[14])とアスタリスクを一つ付けるとp[13]へアクセスします。
アスタリスクが2個になると今度はp[14]の先の先でp[12]へアクセスします(実際には型キャストが必要ですが・・・)、
3個でp[11]
...
14個でp[0]、つまり"Hello World!"の先頭アドレスへたどり着きます。

※正直このような書き方は初めて見ましたがw
※実機で動かしてないので、ちょっといい加減に書きましたが大体合っているはず・・・

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/15 15:28

    {(char*)s.c_str()};はstring型をcharに変換しているという解釈でいいんですかね?

    キャンセル

  • 2018/06/15 15:33 編集

    その解釈は若干怪しいですが、s.c_str()はsが保持している文字配列の先頭アドレス(const char*)を返してくれる関数だったと思います。(char*)と書いてあるのはconstを外すためだと思われます(const外しは推奨されません)。

    キャンセル

  • 2018/06/15 15:34

    なるほどですね
    ありがとうございます

    キャンセル

  • 2018/06/15 15:37 編集

    std::stringである必要はないんですけどね・・・。
    こう書いてもよいです。

    int main()
    {
    char *text = "Hello World!";
    char *p[15];
    p[0] = text;

    for (int i = 1; i < 15; i++) {
    p[i] = (char*)&p[i - 1];
    }

    std::cout << **************(char***************)p[14] << std::endl;;

    getchar();

    return 0;
    }

    キャンセル

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

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

関連した質問

  • 解決済

    文字列の結合をC言語で行う方法

    3つ以上の文字列を結合する方法 例えば・・・ char char_a[10]="aaa"; char char_b[10]="bbb"; char char_c[10]="cc

  • 解決済

    C言語のプログラム!

    C言語のプログラムで、以下のような結果を出力するコードを教えてください! <出力結果> 目的地:東京 ←コマンドプロンプトに東京と入力する 場所:東の方角←東京以外を入力すると

  • 解決済

    C++ string型の二進数をint型の十進数に変換したい

    C++で文字列表記の二進数をint型の十進数に変換したいのですが、そういったメソッドは用意されているのでしょうか? もしない場合、どのようにすれば効率的に求められるでしょうか?

  • 解決済

    C++でchar型の数値を数字列に変換したい

    ログ出力のマクロを作っています。 前提条件として、 1) パラメータに、任意の数値型と任意のポインタ型の値が渡される 2) 数値型の数値を10進の数字列でバッファに出力 3) 

  • 解決済

    OPENCVにおけるエラー

    openCVをはじめようとして、以下のエラーがでました。 プログラミング初心者です。 visual studio community 2017を使っています。 opencv3.3.

  • 解決済

    C++でC#のMemoryStreamと同様の機能をもつクラスはありますか?

     質問 C++でC#のMemoryStreamクラスと同様の機能やクラスはありますか? C++にて可変長バッファを扱うよい方法があればご教示いただきたく、よろしくお願いします。

  • 受付中

    二次元配列のvector(struct)に一元の配列をpush_backしたい。

    cinで行の値、括弧でくくられた3つの値をそれぞれ入力してもらいその値を構造化されたvectorにpush_backしたいのですが、どのようにすればよいのかわかりません。 最終的に

  • 解決済

    charの配列に16進数を10進数にして1つの文字列を表示させたい

    例としてchar型の配列があり、そのなかに 16進数があります。 それを1つのstring型で数値を文字列としてもたせたいのですがどうやればよろしいでしょうか。ご教授願います。

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

  • C++

    3341questions

    C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。