4

constあなたの答えは、私が今日気づいたことについての私の理解におけるこの大きな欠落を解消するために非常に求められています.

私のプログラムでは、ステートメントを使用しましたが、変数iconst int *ptr=&i;に修飾子を使用していません。const

1)を使用してi値を変更しようとすると、変数iを修飾子で宣言していないにもかかわらず、エラーが発生しますptrconst int *ptr=&i;assignment of read-only location '*ptr'|constconst int *ptr=&i;int * const ptr=&i;

これは、ポインターがconst int *ptr=&i;定数のアドレスを格納することをint * const ptr=&i;意味しますが、ポインター自体は定数であり、変更できないことを意味します.しかし、今日、あるユーザーがディスカッション( LINK )で私に言いましたconst int *ptr means the memory pointed to must be treated as nonmodifiable _through this pointer_。これは、「一部の選択ポインターは値を変更できない (他の人は変更できる)」ことを意味するためです。私はそのような選択的宣言に気づいていませんでした!!これをより明確に、より詳細に、より厳密な方法で述べてください。平均?

2)また、非定数のアドレスをポインタに代入することで、ステートメント内のプログラムにをつくことができるとも言われconst int *ptr=&i;ました.これはどういう意味ですか?なぜそれが許されているのですか?なぜ警告が出ないのですか?定数のアドレスを期待するポインターに非定数のアドレスを割り当てるとptr?そして、非定数のアドレスが割り当てられることを非常に許容している場合、その非定数の値を変更しようとするとエラーがスローされるのはなぜですか? -constant、指している変数が非定数である場合、どちらが合理的ですか?

#include <stdio.h>

int main ()
{
 int i=8;
 const int *ptr=&i;
 *ptr=9;
 printf("%d",*ptr);
}

エラー: assignment of read-only location '*ptr'|

4

2 に答える 2

6

定義const int *ptr = &i;は本質的に「私はiを通じて変更しない」と述べていptrます。intptr指している がであるとは言っていませんが、それを変更するために使用すべきではないとconst言っています。ptr

この変換は理にかなっているため許可されています。iis ではないためconst、変更することは許可されていますが、変更しないことも選択できます。変更しないことを選択した場合、ルールが破られることはありませんi。また、ポインタを作成してi「このポインタを使用して を変更するつもりはありません」と言えばi、それも問題ありません。

これを行う理由は、オブジェクトへのポインターを受け取るルーチンにオブジェクトのアドレスを渡すことができるようにするためですconst。たとえば、strlenルーチンを考えてみましょう。ルーチンはそのstrlen入力を変更しないため、そのパラメーターは へのポインターconst charです。へのポインターがありchar、その長さを知りたいです。だから私は電話しますstrlenchar現在、へのポインターであるパラメーターの引数としてへのポインターを渡していますconst char。その変換が機能することを望みます。それは完全に理にかなっています。必要に応じて my を変更できますcharstrlenルーチンは変更しないため、それらを として扱いますconst char

1)へのポインターとして*ptr = something;宣言したため、 でエラーが発生しましたが、を変更するために使用しないという約束に違反しました。そうでないオブジェクトを指しているという事実は、それを変更するために使用しないという約束を否定するものではありません。ptrconst intptrintptrconstptr

2) 非constオブジェクトのアドレスを へのポインタに代入することは嘘ではありませんconst。代入は、オブジェクトがconstであることを示しているのではなく、ポインタを使用してオブジェクトを変更してはならないことを示しています。

さらに、これを尋ねていませんがconst、C の属性は完全にバインドされていません。オブジェクトを と定義した場合は、const変更しないでください。constただし、へのポインターが、それを非へのポインターに変換するルーチンに渡される他の状況がありますconst。これは事実上、言語の欠陥であり、const私たちが好む方法で処理するために必要なすべての情報を保持できないことです。strchrルーティーンはその一例です。その宣言はchar *strchr(const char *s, int c). パラメータsは、その入力を変更しないconst char *ためです。strchrただし、strchrルーチンの派生元のポインターs(文字列内の文字の 1 つを指します)。したがって、内部的には、strchrをに変換しconst char *ましたchar *.

char *これにより、にを渡しstrchr、返されたポインタを使用して文字列を変更するコードを記述できます。これは問題ありません。ただし、これはコンパイラがエラーを完全に防ぐことができないことを意味しconst char *ますstrchr。これは C の欠点です。

于 2013-05-14T14:00:00.027 に答える
-1

これを解明する:

const int *ptr は、「*ptr が const int である」ことを意味します。つまり、「ptr は const int へのポインターです」。*ptr は定数なので *ptr = 9 と書くことはできません。ただし、int j; と書くことはできます。ptr = &j; ポインター ptr が別の int を指すことを許可できるためです。

int * const ptr は、「ptr は int への定数ポインター」を意味します。ptr が指しているアドレスを変更していないため、 *ptr = 9 と記述できます。ただし、それを他のものに割り当てることはできません。つまり、int j; ptr = &j; コンパイルされません。

2 番目の部分 (2) に関しては、const int* ptr があると非常に便利です。特に関数プロトタイプでは、ptr が指している変数が関数によって変更されないことを関数の呼び出し元に伝えるためです。割り当てに関しては、int* m = &i がある場合、ptr = m は問題ありませんが、m = ptr は後者が「constness をキャストする」ため、問題ありません。つまり、const を回避しました。

于 2013-05-14T13:03:45.043 に答える