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言語において、 配列要素をひ...
-
char型配列をint型に代入するには
-
配列のアドレス部
-
C言語の2次元配列 容量が大き...
-
構造体のextern方法
-
C言語の課題丸投げ
-
VB.NETにおける構造体の初期化
-
10人分の生徒の英語の点数{32,3...
-
C++DLLからC#へのコールバック...
-
配列における数値の比較について
-
VC++2010で配列の要素数を取得...
-
行きがけ順で表示するプログラム
-
IPアドレスを配列に代入する方法。
-
[C++]const int と配列
-
n人の教科ごとの最高点、最低点...
-
int i, int i[1];
-
vector配列の重複を無くすには?
-
C言語を使って、ファイルの読み...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数から配列を返すには?
-
配列の要素数に変数を入れたい...
-
define で 配列
-
c言語
-
C#で構造体の配列を持った構造...
-
構造体のextern方法
-
C言語において、 配列要素をひ...
-
C#でのフィボナッチ数列
-
C言語の2次元配列 容量が大き...
-
C#で配列が空かを判定するには?
-
配列のアドレス部
-
char型配列をint型に代入するには
-
C言語の課題が出たのですが自力...
-
2番目の最大値を求める
-
C言語についてです 5人のテスト...
-
C言語から質問です。
-
C言語 ファイルの指定された行...
-
c言語 構造体
-
コンボボックスでデフォルト値...
-
MFCのCArrayを使った二次元配列
おすすめ情報