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

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

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

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

Q&A

解決済

5回答

10793閲覧

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

2BUT4

総合スコア14

C++

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

2グッド

2クリップ

投稿2017/11/25 13:17

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

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

C++

1#include<iostream> 2using namespace std; 3 4const char* const MONTH_NAME[]{ 5"睦月","如月","弥生","卯月","皐月","水無月","文月","葉月","長月","神無月","霜月","師走" 6}; 7 8const char* GetOldMonthName(int month){ 9if(1<=month && month<=12){ 10return MONTH_NAME[month-1]; 11} 12return 0; 13} 14 15int main(){ 16int month; 17 cout<<"今は何月ですか >"<<flush; 18cin>>month; 19 20const char*name=GetOldMonthName(month); 21if(name==0){ 22cout<<"そんな月ねーべさ"<<endl; 23}else{ 24cout<<name<<endl; 25} 26} 27

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

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

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

まとめると、

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

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

keicha_hrs, yohhoy👍を押しています

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

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

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

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

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

guest

回答5

0

ベストアンサー

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

ポインタとconst修飾

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

投稿2017/11/25 15:54

yohhoy

総合スコア6189

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

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

2BUT4

2017/11/25 17:56

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

2017/11/25 18:07 編集

後者の色分け(青/黄)はconstの対象を明示するために入れてみました。 青=文字列(文字そのもの)を変更できない 黄=指し先の文字列を変更できない/別の文字列を指すことは出来ない なおC/C++言語では、配列の数(要素数; この例では12)は、const有無に関わらず変更できません。
2BUT4

2017/11/25 18:43

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

0

こんにちは。

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

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

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 13:56

編集2017/11/25 13:58
Chironian

総合スコア23272

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

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

2BUT4

2017/11/25 18:19

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

0

イメージ説明

投稿2017/11/26 15:08

2BUT4

総合スコア14

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

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

yumetodo

2017/11/26 17:01 編集

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

2017/11/27 14:08

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

2017/11/27 17:38

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

0

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

cpp

1"arikitari";

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

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

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

投稿2017/11/25 14:40

yumetodo

総合スコア5850

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

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

2BUT4

2017/11/25 18:08

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

0

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

投稿2017/11/25 13:41

cateye

総合スコア6851

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

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

2BUT4

2017/11/25 18:30

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問