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

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

ただいまの
回答率

90.48%

  • C

    3825questions

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

  • C++

    3608questions

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

char *, char**, char***の違い

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 8,179

TAKAYUKI_MIWA

score 58

とても疑問に思っていることがあります。
ウェブサイトでCharについて調べていると、"char * * "や"char* * *"と記載してあるコードがありました。

自分なりに検索して勉強してもなかなかイメージじずらく理解できません。申し訳ありませんが、簡単に説明していただくことは可能ですか。

学習中であり、質問が投げやりになってしまい申し訳ありませんが、全く理解できません。

ソースコード

#include <stdlib.h>
#define N      20  // For this example, we will allocate 20 strings
#define LENGTH 10  // of 10 characters each (not counting 0 terminator)
...
char **arr = malloc(sizeof *arr * N); 
if (arr)
{
  size_t i;
  for (i = 0; i < N; i++)
  {
    arr[i] = malloc(sizeof *arr[i] * (LENGTH + 1)); 
    strcpy(arr[i], "          "); 
  }
}

補足情報(言語/FW/ツール等のバージョンなど)

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

+3

こんにちは。

char*は「char型変数へのポインタ型(=char*型)」ですので、ポイント先のchar型変数が格納されているメモリアドレスが入ります。
同様にchar**は「char*型変数へのポインタ型(=char**型)」ですので、ポイント先の「char*型変数」が格納されているメモリアドレスが入ります。
更に同様にchar***は「char**型変数へのポインタ型」ですので、ポイント先の「char**型」が格納されているメモリアドレスが入ります。

char***のような3重ポインタを使う機会はまずない(私は30年以上この業界にいますが一度も使ったことありません。見た記憶もないです。見たと言う噂は聞いたこと有ります。)ので、char**まで理解しておけば十分です。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/03/30 22:59

    横やりで済みません。
    私は若いころ3重ポインタを使ったソースを見たことがあります。しかし当時の先輩から「そういう記述が必要になるということは、設計自体を見直すべきだ」と指導されました。
    当時は高度なテクニックだと思っていたのですが、今現在冷静に考えるとちょっとトリッキーというか必要以上に複雑化したコードのように思えます。自分ではとてもメンテしきれないと思いますのでまず書きません。

    キャンセル

  • 2016/03/30 23:06

    完全にoff-topicですが;世の中広いもので7重ポインタまでは実用例があります http://qiita.com/yohhoy/items/c3f898dafb3d8bc07bd1

    キャンセル

  • 2016/03/30 23:14

    うわっ。6次元配列で7重ボインタですか!! こ、これは超レアものです!!
    3重ポインタでさえ私にとって都市伝説級なのに...世の中本当に広いですね。

    キャンセル

  • 2016/03/31 14:56

    ありがとうございます。

    キャンセル

checkベストアンサー

+1

はじめまして

char c;
と宣言した場合、c は文字を格納する領域です。

c = 'A';

とすると、c の領域に A という文字を格納します。

char *pc;
と宣言した場合、pc は文字を格納する領域の
ポインタ(アドレス)を格納するための領域です。

pc = &c;

とすると最初に宣言した c の領域へのポインタを
pc という変数に格納します。

話を簡単にするために、ポインタのサイズを2バイト
として話を進めます。

この場合で、c が例えば、 0x1000 番地に1バイトで
メモリに確保されたと仮定します。
このメモリの 0x1000 番地には 'A' が格納されます。

この場合で、pc が例えば、0x2000 番地に2バイトで
メモリに確保されたと仮定します。
メモリの 0x2000 番地には、0x1000 が格納されます。

ここまで理解できますか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/03/30 21:36

    分かりやすい説明ありがとうございます。
    とても理解できました。

    ただ、char * と char** や char *** はなんでしょうか。

    キャンセル

  • 2016/03/30 21:55 編集

    続きになります。

    char **ppc;
    と宣言した場合、ppc は文字を格納する領域の
    ポインタ(アドレス)のポインタ(アドレスを)を
    格納するための領域です。

    ppc = &pc;

    とすると2個目に確保した領域を格納します。

    この場合で、ppc が例えば、0x3000 番地に2バイトで
    メモリに確保されたと仮定します。
    メモリの 0x3000 番地には、0x2000 が格納されます。

    さて、なぜこの様な宣言が必要かというと次の例で
    示します。

    int aloc_func(int sz, char **ppc)
    {
      int err = 1;

      *ppc = (char *)malloc(sz);
      if (*ppc != NULL) {
        err = 0;
      }
      return(err);
    }

    void func()
    {
      char *pc;
      int err;

      err = aloc_func(10, &p);
      if (err == 0) {
        // p を使う処理
        free(p);
      }
    }

    関数 aloc_func()では、char * のメモリを確保
    して呼びだし元を返すのですが、確保したメモリ
    を返す為には、確保した char * のメモリを格納する
    char ** の領域が必要となります。

    キャンセル

  • 2016/03/31 14:56

    ありがとうございます。
    とても理解できました。

    キャンセル

0

char*   charへのポインタ
char**  charへのポインタへのポインタ
char*** charへのポインタへのポインタへのポインタ
です。

char*** ppp;
なら、文字型のデータを得るには
***ppp
と言うことです。

言語仕様上は * は3個までということはなく、いくつでも付きます。(付けられます)

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/03/30 23:19

    スマフォからのせいでしょうか?
    *二つで表示が変になっています。

    キャンセル

  • 2016/03/30 23:47

    **はMarkdownの太字指定です。**と**で囲まれた文字列が太字になります。
    油断していると知っていてもハマります。orz
    ``(バッククォート)で括ればとりあえず逃げれます。(文字が赤くなってしまいますが。)

    キャンセル

  • 2016/03/31 14:56

    ありがとうございます。

    キャンセル

  • 2016/03/31 17:25

    書き方を知らなかったので、みっともない回答になってしまいました。
    いまさらですが、Chironianさんのご教示の通り、書き換えました。

    うーーーーん、勉強が足りず、すいません。

    キャンセル

0

誤解を恐れずにざっくりイメージするのなら
char は 'A' 等の大きさのデータを入れるバケツ
char * はそのバケツを入れるためのバケツ
char ** はさらにそのバケツを入れるためのバケツ
…位に考えてもいいかもしれません。
char * は「char を入れるためのバケツを入れるためのバケツ」なので char や int 等は入れられません。
また例えば char a; と宣言してある時に a で参照するとそのバケツ自身ではなく中に入ってる中身を参照しています。
a のバケツ自身を参照したい時には頭に「&」をつけて &a とします。
同様に考えていくと char *b; では char * な b を宣言しているので
charを入れるためのバケツを入れるためのバケツ」である b を宣言しています。
なので b には b = &a; のように「char のバケツ」を入れてやります。
char * が char ** になっても考え方は同様で char ** は「char *を入れるバケツを入れるバケツ」なので

char a = 'A';
char *b = &a;
char **c = &b;

のようになります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/03/31 14:56

    ありがとうございます。

    キャンセル

関連した質問

  • 受付中

    OpenCVで動画の読み込みがうまくできません。

    以前別のプログラムで動画の読み込みができましたが、今現在取り組んでいるプログラムではうまくいきません。 言語はC++でopencv2.4.9を使用しています。 Os windo

  • 解決済

    (char *)とは...

    (char *)の意味 www9.plala.or.jp/sgwr-t/lib/free.html 様のソースコードを読んでいたらむ??となったので質問させていただきました。

  • 解決済

    スタックの応用

    スタックを利用して入力された文字列の回文を作るプログラムを作成したら、出力されません。 例えば、「abcd」と入力したら、「abcddcba」と主著力される。 発生して

  • 解決済

    linux 処理時間の表示

    C言語でLinuxを使っています。メモリを確保したりするプログラムなのですが、以下のプログラムを修正して 、5秒間で何回の入れ替えを行えるかを計測できるようにしてもらいたいです。初

  • 解決済

    ポインタをループ変数として使用する

    いつもお世話になっています。c言語初心者で、勉強中です。ポインタについて質問させて頂きます。課題で、N個(マクロで5と定義してある)の浮動小数データを入力すると 小さい順に並び換え

  • 解決済

    malloc関数、文字化け

    Windows で実験コードを作成していたら、表示がおかしくなりました。 #include<stdio.h> #include<stdlib.h> #include <str

  • 解決済

    スペース区切りの文字列と整数の読み取り

    -入力- N 都市名1 数 都市名2 数 一行目のNがその後何行要素を読み込むか決めています。 -入力例- 2 tokyo 12 honoruru 11

  • 解決済

    iosアプリ(swift/Object-C)でデフォルトゲートウェイのIPアドレスを取得

    iPhone(ios)のアプリのプログラム(swift/Object-C)でデフォルトゲートウェイのIPアドレスを取得したいですが、やり方がわかりません。 色々調べてやってみ

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

  • C

    3825questions

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

  • C++

    3608questions

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