1

char array (string)inの異なる宣言を比較しようとしていCます。

主にこれらの組み合わせを比較した 2 つのポイントがあります (何度も書く代わりに名前を付けました)。

  1. ポイントの変更またはポイントの割り当て :ポインターが指すもののみを変更します。
    char *a, *b;
    a=b //we are doing this
  2. 値の変更:ポインターが指しているデータを変更しています。
    char *a;
    *a='x' //we are doing this

以下は、さまざまな組み合わせのコードです。10個ほど疑問があります。それらはすべてどういうわけかリンクしているので、一緒に尋ねなければなりません。

すべての疑問はコードで説明されています。また、エラー メッセージも追加されます。

すべての質問に対する答えがわからない可能性があります。そのため、コード内の別のセクションにマークを付けました。また、各質問には番号が付けられています。
質問に対する答えがわかる場合は、適切な索引を付けて答えてください。

コードでは、間違っている可能性がある独自の観察と結論も行っています。だから私は結論:タグでそれらをマークしました。結論が間違っている場合は、共有/回答してください。

コード:

#include <stdio.h>

int main() {

    char *p = "Something";//I cant change the data
char q[] = "Wierd"; // I can change to what q points to

// I. ______________________  char*p   ___________________________
printf("\nI. ______________________  char*p   ___________________________ \n\n");

printf("%s %s\n",p, q);
//*p = 'a';// got segmentation fault as I cant change the Value


p = q;//This is possible because I change the Point

//Now the type p is a char pointer which can't change Value (because I declared it like this) but can change the Point
//and it is now pointing to a memory which is of type a char array.I can change its Value but cant change its Point
//This means there are two different things on both sides of the assignment but gcc doesnot give any error (i.e. it is acceptable)
//That is for Pointer assignment restriction rules of the type of left side var was used and for Value change
//rules of the type of right side var was used
// (1)Why?

*p  = 'x';
printf("%s %s\n",p, q);

//Again try to make Something Wierd
p = "Something";
q[0] = 'W';


// II. ______________________  char q[]   ___________________________
printf("\nII. ______________________  char q[]   ___________________________ \n\n");

printf("%s %s\n",p, q);
//q = p;// This is not possible because for q I cant change Point.
// This is the error comes
//error: incompatible types when assigning to type ‘char[6]’ from type ‘char *’

*q = 'x';//This works fine as this is possible to change Value for q
printf("%s %s\n",p, q);

//Again try to make Something Wierd
p = "Something";
q[0] = 'W';

//____________________________________________________________________/

const char * r = "What";//I cant change the data to what a points to (basic def and const act on same)
char const * s = "Point";//I cant change the data to what a points to (basic def and const act on same)
char * const t = "Pointers";//I cant change the data to what a points to because of basic def and const make c a const that now c can only point to single entity.

const char u[] = "Are";//I cant change the data to what a points to because of const and I can't change to what d points because of basic def of [].
char const v[] = "Trying";//I cant change the data to what a points to because of const and I can't change to what d points because of basic def of [].
//char w const [] = "To make";//This is not possible

//___________________________________________________________________/


// III. ______________________  const char * r   ___________________________
printf("\nIII. ______________________  const char * r   ___________________________ \n\n");

printf("%s\n",r);

//*r = 'x'; // This is not possible
//Error comes is:
//error: assignment of read-only location ‘*r’
//now the behaviour of r is same as p but instead of getting segmentation fault I got an error at compile time.
//Also the restriction const put here is same as of restriction present with p except(error checking).
//Conclusion : This means writing const here makes no difference in terms of Value and Point. What it was before is the same now.

r = s;
printf("%s %s\n",r ,s);
//*r = 'x';

r = t;
printf("%s %s\n",r ,t);
//*r = 'x';

r = u;
printf("%s %s\n",r ,u);
//*r = 'x';

r=v;
printf("%s %s\n",r ,v);
//*r = 'x';

r=p;
printf("%s %s\n",r ,p);
//*r = 'x';

r=q;
printf("%s %s\n",r ,q);
//*r = 'x';

//For above four cases
//Everything works for Point assignment 
//Nothing Works for Value change (Everytime assignment to read-only location error, no segmentation fault)

//Everything Works for Point assignment - This means everything works for the 
//rules of the type of varible on the left side for Pointer assignment. (Even for r=u,r=v, r=q).
//(2) WHY this is happening.(Actualy answer related to WHY(1))

//Nothing Works for Value change
//Now this is absurd. On the first look it seems that as the things happen at the time of p=q, here
//for r=u, r=v, r=q same things should had happened. But on the closer inspection you can get that u,v 
//have restrictions on Value change because of const.
//But (3)Why no Value change is happening for r=q ? 
// (4) Why fot r=p, r=q getting error due to const. not due to segmentation fault.



//Resetting Wierdness
r = "What";

// IV. ______________________  char const * s   ___________________________
printf("\nIV. ______________________  char const * s   ___________________________ \n\n");

printf("%s\n",s);

//*s = 'x'; // This is not possible
//Error comes is 
//error: assignment of read-only location ‘*s’
//Behavious of s is exactly same as r
//Conclusion: Writing const after or before char makes no difference.


s = r;
printf("%s %s\n",s ,s);
//*s = 'x';

s = t;
printf("%s %s\n",s ,t);
//*s = 'x';

s = u;
printf("%s %s\n",s ,u);
//*s = 'x';

s=v;
printf("%s %s\n",s ,v);
//*s = 'x';

s=p;
printf("%s %s\n",s ,p);
//*s = 'x';

s=q;
printf("%s %s\n",s ,q);
//*s = 'x';

//For above four cases
//Everything happens same as with r.


//Resetting Wierdness
s = "Point";

// V. ______________________  char * const t   ___________________________
printf("\nV. ______________________  char * const t   ___________________________ \n\n");

printf("%s\n",t);

//*t = 'x';//This is not possible
//Error is
//Segmentation-fault
//This means that on Value change the error comes not due to const. It comes for the same reason of p.

//t = r;
printf("%s %s\n",t ,r);
//*t = 'x';

//t = s;
printf("%s %s\n",t ,s);
//*t = 'x';

//t = u;
printf("%s %s\n",t ,u);
//*t = 'x';

//t=v;
printf("%s %s\n",t ,v);
//*t = 'x';

//t=p;
printf("%s %s\n",t ,p);
//*t = 'x';

//t=q;
printf("%s %s\n",t ,q);
//*t = 'x';

//For above four cases
//Nothing Works for Point Assignment
//Nothing works for value change (Everytime segmentation fault, assignment to read-only location error)

//Nothing Works for Point Assignment
//This is understandable

//Nothing works for value change
// (5) Why this is happening. Why left hand side is always given precedence. Why this isn't happening p=q, 
//because for value change t=q and p=q are exctly same both pn left side and right side of the assignment.


//Resetting Wierdness
//t = "Pointers"; //No need


// VI. ______________________  const char u[]   ___________________________ 
printf("\nVI. ______________________  const char u[]   ___________________________   \n\n");

printf("%s\n",u);

//*u = 'x';//This is not possible
//Error Comes is
//error: assignment of read-only location ‘*(const char *)&u’
//This error comes because of const.
//Conclusion: [] gives the Point restriction and const gives the Value Restriction  


//u = r;
printf("%s %s\n",u ,r);
//*u = 'x';

//u = s;
printf("%s %s\n",u ,s);
//*u = 'x';

//u = t;
printf("%s %s\n",u ,t);
//*u = 'x';

//u=v;
printf("%s %s\n",u ,v);
//*u = 'x';

//u=p;
printf("%s %s\n",u ,p);
//*u = 'x';

//u=q;
printf("%s %s\n",u ,q);
//*u = 'x';

//For above four cases
//Nothing Works for Point Assignment
//Nothing works for value change (Everytime assignment to read-only location error, no segmentation fault)

//Nothing Works for Point Assignment
//Error Comes for each is:  
//warning: assignment of read-only location ‘u’ [enabled by default]
//error: incompatible types when assigning to type ‘const char[4]’ from type ‘const char *’

//Left side rules are given precedence. (6)Why? (If already not solved in above answers)

//Nothing works for value change    
//Left side rules are given precedence. (7)Why? (If already not solved in above answers)




//Resetting Wierdness
//u = "Are";

// VII. ______________________  char const v[]   ___________________________    

printf("\nVII. ______________________  char const v[]   ___________________________  \n\n");

printf("%s\n",v);

//*v = 'x';//This is not possible
//Error Comes is
//error: assignment of read-only location ‘*(const char *)&v’
//This error comes because of const.
//Conclusion: Writing const after or before char makes no difference.



//v = r;
printf("%s %s\n",v ,r);
//*v = 'x';

//v = s;
printf("%s %s\n",v ,s);
//*v = 'x';

//v = t;
printf("%s %s\n",v ,t);
//*v = 'x';

//v=u;
printf("%s %s\n",v ,u);
//*v = 'x';

//v=p;
printf("%s %s\n",v ,p);
//*v = 'x';

//v=q;
printf("%s %s\n",v ,q);
//*v = 'x';

//For above four cases
//Everything works as same with u.


//Resetting Wierdness
//v = "Trying";


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// (8) WHY `const char * a;`  and  `char const * a`  works same?????


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//---------------Now doing more Possible combinations with p and q------------------
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// VIII. ~~~~~~~~~~~~~~~~~~~~~~~~~~~ char *p ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
printf("\nVIII. ~~~~~~~~~~~~~~~~~~~~~~~~~~~ char *p ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n\n");

//p = r;
printf("%s %s\n",p ,r);
//*p = 'x';

//p = s;
printf("%s %s\n",p ,s);
//*p = 'x';

//p = t;
printf("%s %s\n",p ,t);
//*p = 'x';

//p=u;
printf("%s %s\n",p ,u);
//*p = 'x';

//p=v;
printf("%s %s\n",p ,v);
//*p = 'x';

//For above four cases

//Point Assignment
//Warning for p=r, p=s is
//warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]
//Conclusion:Kind of understandable.

// NO Warning for p=t 
//For left side type I can do Point assignment and for Right Side I can,t do.
// Left side rules are given precedence. (9)Why? (If already not solved in above answers)

//Warning for p=u, p=v is
//warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]
//For left side type I can do Point assignment and for Right Side I can,t do.
// Left side rules are given precedence. (10)Why? (If already not solved in above answers)


//Value Change
//Segmentation fault for everything .
//Conclusion: Understndable if assume left hand side are given precedence except for p = q (showed in I.)


//Resetting Wierdness
p = "Something";

// IX. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char q[] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
printf("\nIX. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ char q[] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ \n\n");

//q = r;
printf("%s %s\n",q ,r);
*q = 'x';

//q = s;
printf("%s %s\n",q ,s);
*q = 'x';

//q = t;
printf("%s %s\n",q ,t);
*q = 'x';

//q=u;
printf("%s %s\n",q ,u);
*q = 'x';

//q=v;
printf("%s %s\n",q ,v);
*q = 'x';

//For above four cases

//Point Assignment
//Error for each is:
//error: incompatible types when assigning to type ‘char[6]’ from type ‘const char *’
//Conclusion: Understandable, if assume L.H.S. is given precedence except for p = q (showed in I.)


//Value Change
//Possible for each
//Conclusion: Understndable if assume left hand side are given precedence except for p = q (showed in I.)


//Resetting Wierdness
*q = 'W'; //No need


    return 0;
}

ダニエルの回答は完了です。しかし、さらに2つの単純な疑問:
1)pオブジェクトが文字列リテラル(変更できない)の場合、つまり、右側のオブジェクトのプロパティですが、RHSのqの場合、同じものがありますが、動作が異なります. なぜ、このように一貫性のない設計を行うのか。
2) p の場合、文字列リテラルを変更すると、動作は未定義です。つまり、変更される場合と変更されない場合があります。改めてなぜこんなデザインに。実際、範囲外の配列アクセスの場合、以前に割り当てたことのないメモリにアクセスするため、これは理解できます。また、そのメモリの一部にアクセスする権限がない場合があるため、セグメンテーション違反が発生します。しかし、なぜ時々文字列リテラルを変更できるのでしょうか。なんでそうなの。この背後にある理由は何ですか。

4

1 に答える 1

5
char *p = "Something";//I cant change the data
char q[] = "Wierd"; // I can change to what q points to

pは、変更が許可されていない 10 個の s の配列 (0 ターミネータを忘れないでください)char*の最初の要素を指しています (文字列リテラルを変更しようとすると、未定義の動作になります。ほとんどの実装では、文字列リテラルは読み取り専用で格納されますcharそのような試みはセグメンテーション違反を引き起こしますが、文字列リテラルを変更しようとすると配列が変更され、クラッシュしない可能性があります)。自由に変更pでき、変更可能なオブジェクトを指すように変更された場合は、 を使用してそのオブジェクトを変更できます*p

q6 つの s の配列ですchar(ここでも 0 ターミネータ)。に値を代入することはできませんqが、配列の内容を変更することはできます。

p = q;

p配列の最初の要素を指すようにしますq。そのコンテキストでqは、 はその最初の要素へのポインターに暗黙的に変換されます。実際に起こることも&q[0]そうです。p = &q[0];変更p可能なオブジェクトを指すようになったため、

*p  = 'x';

は許可され、最初charq.

p = "Something";
q[0] = 'W';

変更が許可されていない配列pの最初の要素を再び指し、 の最初の要素を、今度は を使用して、変更前の状態に戻します。charqpq

//q = p;// This is not possible because for q I cant change Point.
// This is the error comes
//error: incompatible types when assigning to type ‘char[6]’ from type ‘char *’

エラー メッセージは少し誤解を招きます。配列を割り当てることはできません。を使用してもchar hello[] = "Hello"; char world[] = "World";、両方の配列が同じ型であっても代入できませんhello = world; produces the same error (since in that context,。world` は最初の要素へのポインターに変換されますが、エラー メッセージは間違っていません)。

*q = 'x';//This works fine as this is possible to change Value for q

そう、*qは と同じq[0]なので、多くの状況で配列をポインタのように (またその逆も) 使用できます。ただし、すべてではありませんが、配列とポインターは異なる種類のものです。

const char * r = "What";//I cant change the data to what a points to (basic def and const act on same)
char const * s = "Point";//I cant change the data to what a points to (basic def and const act on same)

const char *char const *まったく同じ意味で、変更不可能なものへのポインターchar(多くの場合、そのような配列の最初のものです)。

char * const t = "Pointers";//I cant change the data to what a points to because of basic def and const make c a const that now c can only point to single entity.

tは定数ポインターであるため、それが指す場所を変更することはできませんが、型ごとに、指すオブジェクトを変更できます。ただし、この場合、 は文字列リテラルtの最初charを指すため、オブジェクトの指す先を変更することはできませんt(ただし、それは の型の結果ではありませんt)。

const char u[] = "Are";//I cant change the data to what a points to because of const and I can't change to what d points because of basic def of [].
char const v[] = "Trying";//I cant change the data to what a points to because of const and I can't change to what d points because of basic def of [].

繰り返しますが、どちらも同じ意味であり、uv配列const charです。これらの配列の内容を変更することは、その型のために許可されていません。

//char w const [] = "To make";//This is not possible

そうです、これは無効な構文です。配列名と括弧の間に型修飾子を入れることはできません。

//*r = 'x'; // This is not possible
//Error comes is:
//error: assignment of read-only location ‘*r’

のタイプはr、ポイント先のオブジェクトを変更することを禁止しますr(ただし、他のポインターを介して変更することは正当な場合があります)。

//now the behaviour of r is same as p but instead of getting segmentation fault I got an error at compile time.
//Also the restriction const put here is same as of restriction present with p except(error checking).
//Conclusion : This means writing const here makes no difference in terms of Value and Point. What it was before is the same now.

結論は間違っています。たとえば、r変更可能なオブジェクトを指すように変更した場合、 を介してそれを変更することはできません。タイプはそれを禁止しています。ただし、 で変更できます。文字列リテラルへのポインターの場合、通常、違いはコンパイルの失敗とセグメンテーション違反ですが、一般的なケースでは、変更による変更は有効です (通常は a の要素を指している場合でも「機能します」が、これも未定義です)文字列リテラルとは対照的に、通常はクラッシュにつながることはありません)。qrp*r = 'x';*p = 'x';ppconst char arr[10]

r = s;

オッケー、問題ないよ。どのオブジェクトがr指すかを変更します。つまり、 を変更しますが、指すrオブジェクトは変更しませんr

r = t;

また、問題ありません。変更可能なオブジェクトを指している場合t、 を使用してオブジェクトを変更できますが、 を使用することはできtませんr。しかしt、文字列リテラルを指しているので、オブジェクトの指している部分を変更してはいけませんt。ただし、1 つはコンパイル エラーで、もう 1 つはおそらく segfault です。

//Everything Works for Point assignment - This means everything works for the 
//rules of the type of varible on the left side for Pointer assignment. (Even for r=u,r=v, r=q).
//(2) WHY this is happening.(Actualy answer related to WHY(1))

「読み取りconst専用」と読みます。ポインターを持っていることをconst char *r;意味するため、ポインターをchar使用してポインター先のオブジェクトを変更することはできません。オブジェクトを読み取るためだけに使用できます。それが指すオブジェクトがとして宣言されたかどうかはconst問題ではありません。constinの宣言は、他のポインターを介して指されたオブジェクトで何ができるかではなく、使用できるrものを制限するだけです。r

//Nothing Works for Value change
//Now this is absurd. On the first look it seems that as the things happen at the time of p=q, here
//for r=u, r=v, r=q same things should had happened. But on the closer inspection you can get that u,v 
//have restrictions on Value change because of const.
//But (3)Why no Value change is happening for r=q ? 
// (4) Why fot r=p, r=q getting error due to const. not due to segmentation fault.

あなたの「Why(3)」を理解しているかどうかはわかりませんが、正しく理解できれば、変更可能なオブジェクトを指しているため、の*r = 'x';後に動作することを期待していました。それから答えは私が上に書いたものです. の宣言の修飾子は、あなたができることを制限します. それはまた、(4) の型である代入を禁止します。r = q;rconstrrconstr*r = whatever;

//Conclusion: Writing const after or before char makes no difference.

そうですね、constが の前か後にあるかで違い*はありますが。const char *r;指示先の変更に使用できないポインターをchar * const x = q;宣言し、常に同じ場所を指すポインターを宣言します。これを使用して、ポイント先のオブジェクトを変更できます (許可されている場合)。またconst char * const y = q;、変更できない読み取り専用ポインターを宣言します。

//*t = 'x';//This is not possible
//Error is
//Segmentation-fault
//This means that on Value change the error comes not due to const. It comes for the same reason of p.

たまたま文字列リテラルを指している*t = 'x';ため、できません。を指すようにt初期化していれば、それは許可されていたでしょう。tq

//t = r;

変更不可能であると宣言したため、それは許可されtていません。それが指す場所を変更することはできません。

// (5) なぜこれが起こっているのか。左側が常に優先される理由。なぜこれが起こらない p=q かというと、//値の変更に対して t=q と p=q は割り当ての pn 左側と右側の両方で完全に同じだからです。

質問の意味がわかりません。であると宣言tしました。constつまり、 に割り当てることはできませんt。の場合も同じで、プログラムconst int i = 100;に書き込むことはできません。i = 120;

//*u = 'x';//This is not possible
//Error Comes is
//error: assignment of read-only location ‘*(const char *)&u’
//This error comes because of const.
//Conclusion: [] gives the Point restriction and const gives the Value Restriction

右。

//For above four cases

//Point Assignment
//Warning for p=r, p=s is
//warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]
//Conclusion:Kind of understandable.

「種類」だけではありません。を に割り当ててconst char*char*ます。指しているオブジェクトは変更できない場合がありますが、 を使用して変更しようとすることchar *pは正式に有効ですp。ただし、指定されたオブジェクトが変更可能でない場合、文字列リテラルまたはconst修飾子で宣言されている場合、それを変更しようとするpと未定義の動作になります。したがって、const修飾子を破棄するのは危険なことであり、コンパイラはそれについて警告します。ただし、これは完全に正当である可能性があるため、エラーではなく単なる警告です。明示的なキャストを使用して、自分が何をしているか (実行しているかどうかにかかわらず) を知っていることをコンパイラに伝えることができます。

// NO Warning for p=t 
//For left side type I can do Point assignment and for Right Side I can,t do.
// Left side rules are given precedence. (9)Why? (If already not solved in above answers)

char * constaを aに割り当てていchar*ます。ここで失われるものはありません。の値を割り当ててtも変更されず、 のconst後にのみ、指す*アドレスを変更できないことが示されています。t

//Warning for p=u, p=v is
//warning: assignment discards ‘const’ qualifier from pointer target type [enabled by default]
//For left side type I can do Point assignment and for Right Side I can,t do.
// Left side rules are given precedence. (10)Why? (If already not solved in above answers)

と同じp = r;

//Value Change
//Segmentation fault for everything .
//Conclusion: Understndable if assume left hand side are given precedence except for p = q (showed in I.)

セグメンテーション違反は、ポインターが文字列リテラルを指すようにしているためにのみ発生します。を指すようにすると、ポインタが を指すように宣言されているか、または のみを指すように宣言されているかに応じてchar[]、割り当て*ptr = 'x';が機能するかコンパイルされません。のいくつかの配列を投入すると、代入はもちろん に対してもコンパイルされませんが、 (修飾子を破棄することに関する警告とともに)に対してコンパイルされ、プログラムを実行すると未定義の動作が呼び出されます (おそらくクラッシュせず、配列の内容ですが、何かが起こる可能性があります)。const charcharconst charconst char*char*const


追加の質問について:

1) p の場合、 object は文字列リテラル (変更できません) です。つまり、右側の object のプロパティですが、RHS の q の場合は同じですが、動作が異なります。なぜ、このように一貫性のない設計を行うのか。

あなたの考えが違うかどうかはわかりません。char *p = "Something";との両方でchar *p = q;、指定されたオブジェクトのプロパティによって、 のどの使用pが有効かが決まります。この 2 つはどちらもその型によって変更できません (どちらもchar[N]一部の ですN) が、文字列リテラルは標準で定義された特殊なケースとして変更できません。

宣言char *p;(ここでは初期化はありませんが、初期化の有無は関係ありません) はp、それが指すものを変更するために使用できるポインターとして宣言します。しかし、ポイント先のオブジェクトを変更しようとするそのような試みが有効かどうかは、ポイント先のオブジェクトのプロパティによって決まります。

char q[] = "Wierd";

文字列リテラルの内容を配列q(0 ターミネータを含む) にコピーするため、文字列リテラルの変更可能なコピーqで初期化されます。配列内のいくつかをポイントすると、変更可能なオブジェクトがポイントされ、そのような変更は有効です。pcharqp

たとえば、 の型はコンパイルを妨げないため、修飾されたオブジェクトをp指すようにすることは危険です。結局のところ、コンパイラは一般に、その時点で修飾されたオブジェクトを指しているのか、変更可能なオブジェクトを指しているのかを知りません (代入は、変更可能なオブジェクトを指すように作成された からのものである場合もあれば、有効な場所がまったくない場合もあります。constconst char c = 'C'; p = &c;p*p = 'x';pconstconst char*

したがって、割り当てp = &c;により、コンパイラは警告を発するか (少なくともコンパイラの警告レベルが十分に高い場合、たとえば gcc と clang ではデフォルトで有効になっています)、エラーでコンパイルを中止することさえあります (gcc と clang)。-pedantic-errorsフラグを渡す場合はそうしてください)。const char *言語標準で&cは、 を に明示的にキャストせずにその代入を禁止してchar*いますが、必要なのは診断のみであるため、コンパイラは自由に警告またはエラーにすることができます。

ポインターが変更不可能なオブジェクトを指しているときに、ポインターを使用してポインター先のオブジェクトから読み取る場合、それは正当な使用法であるため、割り当ては完全に無条件に禁止されません (キャストを使用すると、標準で許可され、キャストはコンパイラに「自分が何をしているのか知っている」と伝えるため、警告さえ発生しません)。

したがって*p = 'x';、有効かどうかは、指定されたオブジェクトのプロパティによってのみ決定できます。指されたオブジェクトが変更不可能な場合 (またはp有効なオブジェクトをまったく指していない場合)、動作は未定義です。未定義の動作がどのように現れるかは未定義ですが、この場合、通常、セグメンテーション違反 (オブジェクトが書き込み保護されたメモリ領域に存在する場合) か、指定されたオブジェクトが許可されているかのように変更されます (型だけがオブジェクトを変更不可能にし、実装はそのような無効な書き込みを識別するための特別な手段を講じません)。歴史的な理由から type を持つ文字列リテラルの場合char[N]、ほとんどの場合、それらは.rodataプログラムの (読み取り専用データ) セクションに書き込もうとすると、オペレーティング システムによって検出され、セグメンテーション違反が発生します。

2) p の場合、文字列リテラルを変更すると、動作は未定義です。つまり、変更される場合と変更されない場合があります。またなんでこんなデザイン。実際、範囲外の配列アクセスの場合、以前に割り当てたことのないメモリにアクセスするため、これは理解できます。また、そのメモリの一部にアクセスする権限がない場合があるため、セグメンテーション違反が発生します。しかし、なぜ時々文字列リテラルを変更できるのでしょうか。なんでそうなの。この背後にある理由は何ですか。

実用主義。

言語を定義する委員会は、実装者の手を縛りたくありません。未定義の動作を回避することはプログラマーの義務であり、そうしない場合、何が起こってもかまいません。

歴史的に、私の知る限り、文字列リテラルを読み取り専用メモリに保存する実装とそうでない実装がありました。言語が標準化されたとき (作成からほぼ 20 年が経過したため、動作には多くの多様性がありました)、それはほとんどが既存の一般的な慣行の書き起こしでした。コンパイラ、ライブラリ、またはハードウェアの違いにより動作が大きく異なる場合は、できるだけ多くのプラットフォームで適合する実装を可能にするために、未定義または実装定義のままにしました。そのため、一部の実装では文字列リテラルの変更が許可されていましたが、他の実装では許可されていなかったため、委員会は動作を未定義にすることでプログラマーに負担をかけることにしました。

于 2012-10-04T22:29:49.653 に答える