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

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

新規登録して質問してみよう
ただいま回答率
85.48%
C

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

C++

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

Q&A

解決済

4回答

39758閲覧

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

saito.kaz

総合スコア76

C

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

C++

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

0グッド

2クリップ

投稿2016/03/30 11:27

編集2016/03/30 12:26

とても疑問に思っていることがあります。
ウェブサイトで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/ツール等のバージョンなど)

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

こんにちは。

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

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

投稿2016/03/30 13:09

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KoichiSugiyama

2016/03/30 13:59

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

2016/03/30 14:14

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

2016/03/31 05:56

ありがとうございます。
guest

0

ベストアンサー

はじめまして

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 12:31

ShinyaAnan

総合スコア241

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saito.kaz

2016/03/30 12:36

分かりやすい説明ありがとうございます。 とても理解できました。 ただ、char * と char** や char *** はなんでしょうか。
ShinyaAnan

2016/03/30 12:59 編集

続きになります。 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 ** の領域が必要となります。
saito.kaz

2016/03/31 05:56

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

0

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

c

1char a = 'A'; 2char *b = &a; 3char **c = &b; 4 5```のようになります。

投稿2016/03/31 01:19

HiroshiWatanabe

総合スコア2160

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

saito.kaz

2016/03/31 05:56

ありがとうございます。
guest

0

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

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

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

投稿2016/03/30 14:13

編集2016/03/31 08:22
nob.

総合スコア711

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nob.

2016/03/30 14:19

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

2016/03/30 14:47

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

2016/03/31 05:56

ありがとうございます。
nob.

2016/03/31 08:25

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問