5

これらの2つのステートメントについて理論的な質問があります。

p整数と整数へのポインタを想定しますa

a)if(p==a){.....}またはif(p>a)..

b)p=a;

それらはすべて違法であり、b特に危険ですが、標準Cはそれらをどのように考慮しますか?

標準を読んで、それらのいずれかが合法であるか他のものであるかどうか、それらがエラー、未定義の動作、未指定の動作、制約違反であるかどうかを私は見つけませんでした。

数え切れないほどの同様の質問を見て、私は解決策を見つけられませんでした。

4

4 に答える 4

5

すべて違法です。比較を実行するには、両方の側が最も共通のタイプに変換可能である必要があります。割り当ての場合、右側は左側のタイプに変換可能である必要があります。

6.5.16.1の制約で許可されている場合を除き、ポインターを含む変換は、明示的なキャストによって指定されるものとします。

6.5.4、3 ; 6.5.16.1は、nullポインター定数、voidポインター、および_Bool割り当ての場合のいくつかの例外について説明しています。)

ポインターを整数に変換するために明示的なキャストを追加すると、プログラムが再び有効になり、比較からブール値が取得されます。結果は実装に依存します。uintptr_tポインタを整数で格納する場合は、必ず使用してください。

于 2012-05-17T18:23:06.537 に答える
4

C11(n1570)§6.5.8[関係演算子] / 2:

制約

次のいずれかが成立します。

  • 両方のオペランドは実数型です; また
  • 両方のオペランドは、互換性のあるオブジェクト型の修飾バージョンまたは非修飾バージョンへのポインタです。

(実数型とは、整数型、列挙型、実数浮動小数点型、およびchar(§6.2.5/ 17)を意味します)

§6.5.9[等式演算子]

制約

次のいずれかが成立します。

  • 両方のオペランドの算術型は;
  • 両方のオペランドは、互換性のあるタイプの修飾バージョンまたは非修飾バージョンへのポインターです。
  • 1つのオペランドはオブジェクト型へのポインターであり、もう1つは修飾または非修飾バージョンの;へのポインターです。voidまた
  • 一方のオペランドはポインターで、もう一方はヌルポインター定数です。

§6.5.16.1[簡単な割り当て]/1:

制約

次のいずれかが成立します。

  • 左側のオペランドはアトミック、修飾、または非修飾の算術型であり、右側は算術型です。
  • 左側のオペランドには、右側の型と互換性のある構造体または共用体型のアトミック、修飾、または非修飾バージョンがあります。
  • 左側のオペランドには、アトミック、修飾、または非修飾のポインター型があり、(左オペランドが左辺値変換後に持つ型を考慮すると)両方のオペランドは 、互換性のある型の修飾または非修飾バージョンへのポインターであり、左側が指す型にはすべてがあります。右が指すタイプの修飾子。
  • 左側のオペランドには、アトミック、修飾、または非修飾のポインター型があり、(左オペランドが左辺値変換後に持つ型を考慮すると)一方のオペランドはオブジェクト型へのポインターであり、もう一方は修飾または非修飾バージョンへの ポインターvoidです。 、および左が指す型には、右が指す型のすべての修飾子があります。
  • 左側のオペランドはアトミック、修飾、または非修飾のポインターであり、右側はヌル ポインター定数です。または、左側のオペランドのタイプがアトミック、修飾、または非修飾_Boolであり、右側が ポインターです。

基本的に、3つの式はすべて、式に設定された制約に違反していました。


制約に違反するとはどういう意味ですか?エラー?しかし、制約に違反すると翻訳が失敗するということはどこにもありません。C規格はあまり明確ではないようですが、最も近い解釈は次のようになります。

§4[適合性]/2:

制約または実行時制約の外側に表示される「shall」または「shallnot」要件に違反した場合、動作は定義されません。

しかし、これは制約の外側について話します。および§5.1.1.3[診断]/1:

動作が未定義または実装として明示的に指定されている場合でも、前処理の変換ユニットまたは変換ユニットに構文規則または制約の違反が含まれている場合、準拠する実装は少なくとも1つの診断メッセージ(実装定義の方法で識別される)を生成する必要があります-定義されています。他の状況では、診断メッセージを生成する必要はありません。

したがって、コンパイラは少なくともメッセージを生成する必要があります(gccで確認できます)が、その後に何をすべきかについては述べていません。

この段落の後の例はそれを述べています

実装は、翻訳ユニットの診断を発行する必要があります。

   char i;
   int i;

この国際規格の文言が構成の振る舞いを制約エラーであり、未定義の振る舞いをもたらすと説明している場合、制約エラーは診断されなければならないからです。

および§6.7[宣言]/3は、制約に違反すると未定義の動作が発生することを明示的に言及していません。

したがって、3つの式はすべて未定義の動作であり、診断メッセージが付随していると推測されます。

于 2012-05-17T18:38:06.583 に答える
0

a)とb)はどちらも制約違反です。 C99、§6.5.8、§6.5.9、および§6.5.16.1。

于 2012-05-17T18:35:14.397 に答える
-1

私が実際にあなたの質問に答えているかどうかはわかりませんが、ここに行きます。a)に関しては、比較があるので、基本的には「ポインタにメモリアドレスがありますか?」ということです。b)では、ポインタに値aを割り当てています。これは、メモリアドレス「a」を指すことを意味します。ここにいくつかのヒントがあります:

p=&a

これで、ポインタは整数aのメモリアドレスを指しています。

*p=a

ポインタが指している値は、aの値を取ります。

p=a

これで、ポインタはメモリ値aを指しています。

お役に立てば幸いです。

于 2012-05-17T18:32:37.753 に答える