![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?c9bd177)
constを使って、配列のアドレス&値の変更を禁止させたのですが
以下のコードを書くと変更できてしまいます。(テスト環境は、Visual C++ .NET 2003 です。)
void CtestDlg::myAAA()
{
char hoge[] = {1,2,3};
const char const *kari = hoge; //配列kariからは変更不可
myBBB(kari);//配列kariのアドレスを渡す
}
void CtestDlg::myBBB(const char const *pBuffer)
{
//pBuffer[1] = 99; //これをするとエラー
*(int*)pBuffer = 6;; //キャスト
//元のhoge配列の中身も変わっている
}
const の用途は、「変更できない」じゃなくて「変更しちゃだめ」って注意を促す
だけなのでしょうか??
そもそも何がやりたいかと言いますと、
例えば、myAAA関数とmyBBB関数をそれぞれ違う人が記述する場合、
myBBB関数 の作成者がどんなコードを書いても配列hogeが上書きされないように
myAAA関数で変更禁止処理をかけたいのですが・・・アドレスを渡す時点でそれは不可能なのでしょうか?
No.2ベストアンサー
- 回答日時:
どちらかといえば、「変更しちゃだめ」です。
そして、通常はそれで十分に変更禁止の役に立ちます。
例示の「強引なキャスト」はルールを破る数少ない手段です。
> *(int*)pBuffer = 6;; //キャスト
変更できるのは、(int*)で*無理やり* constでない型にキャストしているためです。
(int*)のようなキャストはC言語との互換性のために残っている代物で、
constを無理やりはずすことができますので、*そんなコードを書く奴が悪い*ということになります。
# C++用に用意されたキャストでは、const_castという専用のキャストが必要です。
# そして、const外しは未定義動作になる可能性も含め通常やるべきものではありません。
基本的にC++はプログラマは全能である、
コンパイラはありがちなミスを避けるための規制をかけるが、
プログラマは必要に応じて*明示的に*その制限を回避する手段がある、
ということが多いです。
言語はプログラマの意図を表現するための道具であり、
プログラマの意図を正しく表現できない言語は実用的でない、
という思想だと理解しています。
詳しい解説ありがとうございます。
偶然見つけたのですが、既知の事実だったのですね・・。
「const外し」で検索したら一杯引っ掛かりました。
const外しはバグではなく、(思想的観点から)敢えて残しているのですね。
No.5
- 回答日時:
>早速の回答ありがとうございます。
>このやり方では保証できないのですね。
どうも勘違いしているような気がしてならない。
保証する責任を負っているのは myBBB() の実装担当者です。
myAAA() 実装担当者ができることは、CtestDlg::myBBB(const char* pBuffer)
が「そのインターフェイス設計に反して」pBuffer の指す内容を変更してしまうと知った時点で、
そのバグを myBBB() の実装担当者に修正するよう要求することだけです。
No.4
- 回答日時:
constについては他の回答者さんが回答されているので。
> myBBB関数 の作成者がどんなコードを書いても配列hogeが上書きされないように
> myAAA関数で変更禁止処理をかけたいのですが・・・アドレスを渡す時点でそれは不可能なのでしょうか?
そうですね、むしろmyAAAの作者はhogeへのポインタをそのまま渡さないようにする。
配列hogeに対応するクラスをつくり、hogeを操作するメソッドを実装してmyBBBの作者にはそれを使ってhogeにアクセスしてもらう。
そうすればmyAAAの作者はメソッドを実装する手間がかかる代わり、自分が公開した処理だけをそのクラスを使う者に許すことが出来ます。
安全性でいえばこれがスマートだと思うのですが、いかがでしょう?
間接的に操作させるイメージでいいのでしょうか?
例では、簡単のため同クラスの関数で書いたのですが、それぞれ別クラスの場合
アクセス方向が myAAA⇔myBBB, myAAA→myBBB, myAAA←myBBB の場合でいろんな方法がありそうですね。
参考にしてみたら?というページがありましたら是非教えて下さい。
回答頂けた方どうもありがとうございました。
No.3
- 回答日時:
>myAAA関数で変更禁止処理をかけたいのですが・・・アドレスを渡す時点でそれは不可能なのでしょうか?
それはシステムに依存します。
組み込み系では const を ROM 上に配置するするものがありますがその場合は物理的に書き込み出来ません。
また、MMUで書込み禁止に設定できる場合は書き込みをしたときに例外が発生するように出来ます。
そうでない場合には禁止できませんね。
どうしても禁止したいのであればポインタで渡すのをやめるしかないでしょう。
組み込み系だと、const宣言時にROMに割り当てられるので上書不可なんですね。
ただ、組み込み開発の環境があったので試しにコンパイルしてみたら
通りました(汗)。一応、警告はでましたが・・・
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# const char** p;のとき、free(p)でC4090エラーとなるのはなぜですか 3 2023/03/31 16:28
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- Excel(エクセル) エクセルVBA、ファイル名をセルの値で保存の方法を教えてください。 おそれいります。こちらで数々のエ 6 2023/06/30 22:17
- Windows 10 バッチファイルの記述法とルールについてアドバイスをお願いいたします。 1 2022/04/13 10:50
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# Cの関数の引数のconst *charについて 5 2023/04/25 13:05
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
- JavaScript javascriptで文字分割は、 split() などメソッド不要??? 4 2023/02/06 22:50
- Visual Basic(VBA) 【Excel VBA】自動メール送信の機能追加 5 2022/09/29 12:53
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数から配列を返すには?
-
C言語において、 配列要素をひ...
-
Cのエラー
-
2つの要素をペアで管理する方法
-
C言語の2次元配列 容量が大き...
-
MFC - ダイアログボックスのPic...
-
char型配列をint型に代入するには
-
fclose()でセグメンテーション違反
-
c言語
-
ListViewのソートについて
-
戻り値で構造体を返すことは可...
-
セグメントエラー
-
C言語 配列の長さの上限
-
System.IO.Directory.GetFiles...
-
プーさんのマウスポインタを教...
-
DataGridView の sort
-
ファイル名「1.jpg ~10.jpg~...
-
Functionの戻り値を2次元配列...
-
LPSTR型の初期化について
-
VBAのプログラムで、DIAG = 1# ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
おすすめ情報