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

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

ただいまの
回答率

91.36%

  • C++

    2412questions

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

ポインタにつけるconstについて※イメージ図有り(C++)

解決済

回答 5

投稿 2017/11/25 22:17

  • 評価
  • クリップ 1
  • VIEW 391

2BUT4

score 6

自分なりに解釈したポインタとconstについてのまとめ

以下にわからなかったコードを記載します。(そのままのコードです)

#include<iostream>
using namespace std;

const char* const MONTH_NAME[]{  
"睦月","如月","弥生","卯月","皐月","水無月","文月","葉月","長月","神無月","霜月","師走"
};

const char* GetOldMonthName(int month){
if(1<=month && month<=12){
return MONTH_NAME[month-1];
}
return 0;
}

int main(){
int month;
 cout<<"今は何月ですか >"<<flush;
cin>>month;

const char*name=GetOldMonthName(month);
if(name==0){
cout<<"そんな月ねーべさ"<<endl;
}else{
cout<<name<<endl;
}
}

このコードを読もうとしたら、最初のconst char* const MONTH_NAME[]のところがわからなくなりました。

const char*は載せたイメージ図で考えると、他のアドレスを代入できないようにするconstで、
const MONTH_NAME[]はこの、MONTH_NAME[]配列に、{ブロック内の月の読み方}以外の値を代入できない

そもそもこの配列はなんのアドレスをいれているのですか?
ポインタがついている変数、配列はアドレスを入れるだけのものではないのでしょうか?

まとめると、

【わからないこと】
・ポインタと定数について、上に載せたイメージ図の考え方であっているかどうか
・わからなかったコードのポインタはそれぞれどこを参照しているのか(わたしの図であれば、*pは変数aを参照している)

*だらけでこんがらがってしまいました。
ちなみにこちらのコードが載っている参考書は【ロベールのC++入門講座】です。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 5

checkベストアンサー

+8

ポインタ変数とconst修飾の関係は下図を参考にください。赤枠がconstの適用範囲、つまり読取専用/変更不可を意味します。

ポインタとconst修飾

配列MONTH_NAMEのメモリイメージと、それぞれの文字列リテラルの関係は下図を参考にください。
文字列リテラルと配列

投稿 2017/11/26 00:54

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/26 02:56

    とてもわかりやすい図です!わたしが知りたかったことをわかりやすくまとめてくださってありがとうございます!
    前のconstと後のconstの色分けのところの意味は、青のほうが要素に入っている「中身」が変更できない、黄色のほうが配列の「数」が変更できない、ということであっていますでしょうか?
    お時間ありましたら、返信していただけるとうれしいです。

    キャンセル

  • 2017/11/26 03:07 編集

    後者の色分け(青/黄)はconstの対象を明示するために入れてみました。

    青=文字列(文字そのもの)を変更できない
    黄=指し先の文字列を変更できない/別の文字列を指すことは出来ない

    なおC/C++言語では、配列の数(要素数; この例では12)は、const有無に関わらず変更できません。

    キャンセル

  • 2017/11/26 03:43

    「配列の数(要素数)は変更できない」検討ちがいな質問をしてしまってすみません・・
    指し先の文字列の固定!ですね。ようやくふわふわとですが理解できました!セットで固定されているようなイメージがなんとなくですが。
    自分で考えてコードが打てるまで、他の問題にも挑戦してみます!
    ありがとうございます!

    キャンセル

+5

こんにちは。

・ポインタと定数について、上に載せたイメージ図の考え方であっているかどうか

あってます。なかなか正確な理解だと思いますよ。

const char*は載せたイメージ図で考えると、他のアドレスを代入できないようにするconstで、

でも、これはイメージ図の理解と違ってます。「他のアドレス(char*型)」ではなく「他の値(char型)」を代入できないようにするconstです。このconstはcharにかかっていると考えると分かりやすいです。
つまりchar型の変数をリードオンリーとして指定しています。const char* p;ならば、*pはchar型であり、*pがconstです。

const MONTH_NAME[]はこの、MONTH_NAME[]配列に、{ブロック内の月の読み方}以外の値を代入できない

日本語の表現としては合っています。でも、2BUT4さんは、例えばMONTH_NAME[0]はchar型と考えているように見えます。この推測が当たっているなら、間違っています。

const char* const MONTH_NAME[]={...};

からconstを外すと

char* MONTH_NAME[]={...};

argv[]と同じ型ですね。argv[0]はchar*型です。同様にMONTH_NAME[0]もchar*型です。

さて、constを戻すとMONTH_NAME[0]はconst char*const型です。
イメージ図に従い、const MONTH_NAME[0]はリードオンリーなのでポインタを代入できません。
そして、MONTH_NAME[0]はconst char型を指すポインタですから、const char型である*MONTH_NAME[0]に値を代入できません。


しかし、ややこしいですね。
私はこのややこしさが嫌いなので、char const* constと書きます。const char* constと意味は全く同じです。
constは型修飾子ですが、constの修飾先が混乱しやすい場合は、このように書くことで左側にある型を修飾していると考えることができます。

char const*のconstはchar型を修飾し、char* constのconstはchar*型(char型を指すポインタ)を修飾します。


constが右側を修飾していると考えると、const char*のconstがcharを修飾しているのかchar*を修飾しているのか分かりにくいです。
日本語にすると「constなchar型を指すポインタ」となりますがconstがchar型を指すのか「char型を指すポインタ」を指すのか曖昧なのです。

投稿 2017/11/25 22:56

編集 2017/11/25 22:58

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/26 03:19

    ひとつひとつ丁寧に、書いてくださって本当にありがとうございます!
    自分で図を書いておいて質問のときに間違えていたのですね・・最初のconstはcharにかかっている、という説明がすごくわかりやすかったです!Chironianさんが言われたとおり、MONTH_NAME[0]をchar型だと思っていました。ここの理解が難しくて迷っていたので本当に助かりました!
    何度も読み直して、もっとちゃんと身につけたいです。
    返信ありがとうございました!

    キャンセル

+1

大体他の方の回答で解決していそうですが、補足するなら文字列リテラルについてでしょうか。

"arikitari";

こういうものを文字列リテラルと呼びますが、この方はconst指定された配列型です。かりにこの文字列がUTF-8でエンコードされたと仮定すると、この文字列リテラルの型はconst char[10]型です。

そしてC/C++では配列は3つの例外を除いて式中では常にポインタに読み替えられます。つまりconst char*型として扱われるわけですね。

さて。この文字列リテラルが実行時にどこに実体を持つかですが、まあこれは環境に大きく依存するのですが、いずれにせよ実行ファイルに文字列が埋め込まれ、実行時にこれがメモリー上に展開されます。
つまり文字列リテラルは例の3つの例外を除いてこのメモリー上に展開された文字列へのポインタといえるわけですね。

投稿 2017/11/25 23:40

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/26 03:08

    yumetodoさん、またまた返信ありがとうございます!
    必ず変数のアドレスをポインタの変数にいれないといけないと思っていました。
    文字列リテラルのことも全然わかってなかったので、回答してくださってとてもありがたかったです!

    キャンセル

+1

![イメージ説明](5cc0b16ca2303dcd2e1b405c0649d399.jpeg)

投稿 2017/11/27 00:08

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/27 02:01 編集

    >初期化した文字列以外の値を代入できない
    そうじゃない。文字列を書き換えられないんだ。ただの配列なんだから代入もくそもない。

    キャンセル

  • 2017/11/27 23:08

    ご指摘ありがとうございます。
    代入、という概念そのものがよくなかったのですね。型の前についたconstは、その値を書き換えられないようにするため、と覚えて問題ないでしょうか?

    キャンセル

  • 2017/11/28 02:38

    正確には読み取り専用である、でしょうか。またJavaと違い実行時にconstかは確認しません。あくまでコンパイル時の判定です

    キャンセル

0

他からの引用ですが、「constの右側にあるものが定数になる」と覚えればよい。
引用元”constの位置について”

投稿 2017/11/25 22:41

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/26 03:30

    引用元のページを見てみたら、ぴったりわたしが迷ってるところの話でした。
    constの右側にあるものが定数、という考えでもポインタになると、constが2つもでてきてしまってこんがらがってしまいました。
    いろんな人の回答が見れてありがたいです!返信ありがとうございます!

    キャンセル

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

ただいまの回答率

91.36%

関連した質問

  • 解決済

    opencvのcvConvertScaleAbs関数エラーを直したい

    こんにちは。 どうしても解決できず、ずっと悩んでいるのでご助力いただけないかと思い投稿しました。 前提・実現したいこと XcodeでC++、opencvを用いて行列操作を

  • 受付中

    char (*p)[10]の使い道

    char (*p)[10]; >>>char型の要素を10個持つ配列へのポインタ! これの使い道がわかりません。 int (*arp)[10]; // アドレスを入れる

  • 受付中

    strcpyのエラーに関して

    ある文字列の配列から大文字だけを抽出してそれを別のchar配列に保存したいのですがエラーになります。どのようにすればよいのでしょうか。 char main_array[50]

  • 解決済

    MQL4(メタトレーダー4)からMySQLに接続できない

    やりたい事 メタトレーダー4からMySQLに接続したい 使用ツール MySQL 5.7.18 Connector/C 6.1.10 MT4 MetaEditor(下記コードの

  • 受付中

    16進数の数値をASCII文字に変換したい

    この対応表のように16進数の数値をASCII文字へ変換するにはどうすればいいですか? 例えば、(0x)30 という数値なら、0と表示したいです。 参考になるサイトなどを教え

  • 解決済

    char型の配列変数にchar型の変数を代入したい

    使用言語 C 環境 Visual Studio 2017 初めての質問です。 独学でプログラミングを始めたのですがわからないところがあり困っています。 char型の配列変数の使い方

  • 解決済

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

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

  • 解決済

    【vector】vector.erase()を高速化したい

     解決済みですが、まだまだこんなのあるよ!という方のコメントを随時募集してます! 前提・実現したいこと タイトルの通り、C++のSTLコンテナの一つvectorクラスの"vecto

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

  • C++

    2412questions

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