web-dev-qa-db-ja.com

「const」は、読み取り専用またはそれ以上を意味するだけですか?

constはどういう意味ですか?読み取り専用は私にとってその意味をカプセル化しているようですが、私が正しいかどうかはわかりません。

読み取り専用とconstが異なる場合、誰かが理由を教えてもらえますか?

この質問のきっかけとなったのは this answer であり、const "just"はCでは読み取り専用を意味します。これはallconstは、CであるかC++であるかに関係なく、意味します。彼はどういう意味ですか?

CとC++でのconstの具体的な違いに対する回答として、新しい質問を作成しました: 「const」はCとC++でどのように異なりますか? Rと同じです。さんの提案。

32
Kim Sun-wu

変数をconstとして宣言することで、その変数を変更する意図がないことをコンパイラーに示します。しかし、それは他の人が持っていないわけではありません!これは、最適化を可能にし、コンパイルエラーによって通知されるようにするためです(注:ほとんどの場合はコンパイルエラーですが、const == ReadOnlyはランタイムエラーを意味します)。

const読み取り専用を意味しません。const volatileを記述できるため、いつでもそれ自体で変更される可能性がありますが、私はそれを変更するつもりはありません。

編集:これは古典的な例です:メモリマップされたポートから現在の時間を読み取るコードを書いていると考えてください。 RTCがメモリDWORD 0x1234にマップされていることを考慮してください。

const volatile DWORD* now = (DWORD*)0x1234;

これはconstです。これは、読み取り専用のポートであるためです。また、volatileは、読み取るたびに変更されるためです。

また、多くのアーキテクチャでは、グローバル変数を変更するのはUBであるため、グローバル変数をconstとして効果的に読み取り専用にしています。これらの場合、UBは実行時エラーとして現れます。他の場合では、それは本当のUBになります:)

これは良い読みです: http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

49
ruslik

コンパイラは、constとして宣言されたものを変更することを許可しません。あなたの言う通りです。

これは主に関数プロトタイプで使用され、関数がこれに触れないこと、またはポインターが渡されたときにそのことをユーザーに通知します。それはまたあなた自身にとって一種のフェイルセーフとして機能します。

7
slezica

多くの人がconstは変更できないことを意味すると言っています。あれは 明らかに偽りconstは簡単にキャストできます。このスニペットに注意してください:

void foo(const int *somevalue)
{
   int *p = (int*) somevalue;
   *p = 256;  // OMG I AM EVIL!!!!11
}

コンパイラはこれをやめさせません。では、constの目的は何でしょうか。私はそれをもっと提案と呼んでいます。関数が期待するコントラクトの関数プロトタイプを見て、それを思い出させます。あなたが不注意にそれを壊すなら、あなたのコンパイラはあなたに怒鳴ります。 (ただし、上記のキャストのように意図的に壊した場合は除きます。)

場合によっては、標準が意図的にconstを壊しています。たとえば、strstrの戻り値に注意してください。定義により、提供するconstバッファーにオフセットが返されます...しかし、戻り値はconstではありません。どうして?まあ、これは、strstr以外のバッファでconstの戻り値を使用すると、意味のある中断を引き起こします。

2
asveikau

2バイトごとに同一(コメントを除く)の最小ケースの例...

最初にCで、gccは警告を出します...

/*関数は、
 2つの読み取り専用整数の配列へのポインタを取ります。*/
 void a(const int(* parray)[2]); 
 
 void b(void)
 {
 int array [2] = {1,2}; 
 const int crray [2] = {1,2 }; 
/* Cはこれを読み取り専用の場所に隠しておく権利を留保します。*/
 
 a(&array); 
/*警告:互換性のないポインタタイプから「a」の引数1を渡します*/
 a(&crray); /* OK!*/
}

C++でも同じことが言えます... g ++はそれでかなり満足しています。

 //変更しないことが約束されている2つの整数の配列
 //へのポインターを受け取る関数。 
 //(constnessをキャストしない限り;-P)
 void a(const int(* parray)[2]); 
 
 void b( void)
 {
 int array [2] = {1,2}; 
 const int crray [2] = {1,2}; 
 
 a(&array); // C++はこれで問題ありません。
 a(&crray); // OK!
}
1
John Carter
const char * hello_1{ "Hello!" };
const char   hello_2[]{ "Hello!" };
char       * ptr{};

// take away the const-nes
// ptr = (char *)hello_1;
// *ptr = '*'; <-- write access violation
// hello_1 is in a read only memory

// take away the const-nes
ptr = (char *)hello_2;
*ptr = '*'; // <-- OK
// hello_2 is modifiable

ポインタはメモリを指し、char *は読み取り専用のデータセグメント内のメモリを指します。 char *char []の違いは、どちらもデータセグメントで同じように宣言されている一方で、char []は、使用されている場合はスタックにプッシュされるため、読み取り可能として扱われることです。

0
user5560811