2016-04-24 19 views
10

C11標準ISO/IEC 9899:以下の技術的な合法性

つ保有していなければならない::2011(E)は§6.5.16.1/ 1で、単純な割り当てについては、以下の制約が述べ

  • 左のオペランドには、アトミック、修飾、または非修飾の算術型があり、右には 算術型があります。
  • 左のオペランドには、アトミック、修飾、または修飾されていないバージョンの構造体または共用体があり、右の型と互換性のある型 があります。
  • 左オペランドは、両方のオペランドが互換性のあるタイプの修飾または非修飾バージョンに ポインタであり、タイプは を指摘し、原子修飾、または非修飾ポインタ型を有し、かつ(左オペランドは左辺値変換後だろう タイプを考慮して)左には、右に指し示されているタイプのすべての修飾子があります。
  • 左オペランドは、原子修飾、または非修飾ポインタ型を有し、一方のオペランドがオブジェクト型へのポインタ であり、他方はへのポインタである(左のオペランドが左辺値変換後だろう タイプを考慮して) voidの修飾子付きまたは修飾子なしのバージョンであり、左側が指し示す型は、右に を指す型のすべての修飾子を持ちます。
  • 左のオペランドは、アトミック、修飾、または非修飾ポインタであり、右はNULL ポインタ定数です。または
  • 左のオペランドは、アトミック、修飾、または非修飾のタイプ_Boolを持ち、右はポインタです。

私は両側がvoid異なる互換性のない型へのポインタである場合には興味があります。私が正しく理解していれば、この制約に違反するので、これは少なくともUBを呼び出すべきです。互換性のない型の1つの例は、(6.1.7および6.7.2に従って)intおよびdoubleである必要があります。

したがって、次のプログラムは、違反にする必要があります:

int main(void) { 
    int a = 17; 
    double* p; 
    p = &a; 
    (void)p; 
} 

どちらもgccと打ち鳴らすには、「-Wincompatibleポインタ・タイプ」について警告が、(-std=c11 -Wall -Wextra -pedanticでコンパイル)コンパイルを中止しないでください。

同様に、次のプログラムは "Wint-conversion"警告のみを表示し、コンパイルは正常です。

int main(void) { 
    int a; 
    double* p; 
    p = a; 
    (void)p; 
} 

C++から来ているので、いずれかのテストケースでコンパイルするためにキャストが必要になると思いました。いずれかのプログラムが標準法的になる理由はありますか?あるいは、-std=gnu11の代わりに-std=c11を明示的に使用して面白いGNU C拡張機能を無効にしても、このコードスタイルをサポートする歴史的な理由は少なくともありますか?厳密な規格準拠のためのチェックを要求すると不適合コードをコンパイルすることを拒否する

答えて

3

コンパイラフラグ(GCCと打ち鳴らす両方)-pedantic-errorsである:

$ gcc -std=c11 -pedantic-errors x.c 
x.c: In function ‘main’: 
x.c:3:15: error: initialization from incompatible pointer type [-Wincompatible-pointer-types] 
    double* p = &a; 
      ^

クラン:

$ clang -std=c11 -pedantic-errors x.c 
x.c:3:11: error: incompatible pointer types initializing 'double *' with an 
     expression of type 'int *' [-Werror,-Wincompatible-pointer-types] 
    double* p = &a; 
     ^ ~~ 
1 error generated. 

かなりの割合(野生の典型的なCコードの不一致がありませんので、-pedantic-errorsはほとんどのCプログラムとライブラリのコンパイルに失敗します。

+0

いいえ、それはツールチェーンの問題です。私のマシンでは、gccとclangの両方が診断結果を出力します。そうではありません、 '-pendantic'は行く方法ではありません。方法は、プラットフォームを更新することです。 –

+0

GCCは明らかにこれを警告しますが、間違ったCコードのコンパイルを止めるには '-pedantic-errors'が必要です。 – Lundin

4

コード例と標準の引用が一致しません。この例は、初期化と割り当てについての6.5.16の話です。

紛らわしいことに、紛らわしいことに、マッチングタイプの要件は、割り当てのための制約セクション6.5.16にありますが、セマンティクスセクション(6.7.9)の「初期化」のための「のみ」です。したがって、コンパイラは、初期化のための診断を発行しないという「正しい」権利を持っています。

Cでは、制約違反は「診断」のみを必要とするため、コンパイラはコンパイルを続けることができますが、結果として得られる実行可能ファイルが有効であるという保証はありません。

私のプラットフォームでは、Debianのテストでは、どちらのコンパイラでもオプションのない診断が得られますので、インストールはかなり古いものでなくてはなりません。

+0

もちろん、私は(これを書いている途中で)初期設定への割り当てを短くしたということは間違いありません。それにもかかわらず、両方のコンパイラの動作は同じように割り当てられます。 –

+3

§6.7.9/ 11にも注意してください。この場合は、この場合はassignemntと同じ方法で扱われます: "スカラーの初期化子は、単一の式でなければならず、必要に応じて中括弧で囲みます。 オブジェクトは式のものであり(変換後)、同じ型の 単純な代入の場合のような制約と変換が適用され、スカラーの型は宣言された型の非修飾バージョンになります。 –

+1

私は自分自身に驚きましたが、スタンダードの状態が2つの間で異なっていることがわかりました。問題の現実については、私の編集をご覧ください。 –

4

いずれかのプログラムが標準法的になる理由はありますか?

これらのプログラムは「標準準拠」ではありません。それらには制約違反が含まれており、すでに標準の正しいテキストを引用しています。

コンパイラは、制約違反の診断を生成することにより、標準に準拠しています。制約違反またはその他の誤ったプログラムの場合、標準でコンパイルを中止する必要はありません。

多くの言葉では言わないが、制約違反を含むプログラムの結果として生成された実行可能ファイルは、完全に未定義の動作をするという妥当な結論しか得られていない。 (私は人々が別の方法で論争しようとしているのを見た)。

推論は次のとおりです。C(およびC++)は多くの目的で使用されています。時々人々はマシンのために "高レベルのアセンブラ"を望んでおり、移植性や標準を気にしません。おそらく、コンパイラのベンダーは、ターゲットオーディエンスが好むと思われるものにデフォルトを設定していました。

+0

コンパイルに失敗した場合にビルドシステムが古いバージョンのコードを残すことはまれではありません。コンパイルに失敗した後にプログラムを実行しようとすると、プログラムの以前に正常にコンパイルされたバージョンが何をしていても、現在のバージョンが何をしようとしているかとは関係ないかもしれません。したがって、このような行為は、スタンダードが現在のバージョンのコードについて言うことのできる管轄区域の外にあります。 – supercat

2

ありませんが、


はい、それは本当にとても簡単です。

Venn diagram of conforming code

いいえ、法的基準ではありません。はい、重要歴史的な理由。

Cはもともとキャストを持っていませんでした。システムプログラミング言語として、それを超強力な栄誉を与えられたアセンブラーとして使用することは合理的であるだけでなく、ベストプラクティスであり、実際には「唯一の実践」でした。

重要な情報は、物事を明るくするはずです。実際には、仕様を実装または強制するコンパイラの仕事ではありません。仕様は、実際には、文字通り、唯一の提案です。コンパイラの実際の仕事は、C11より前、C99より前、C89より前、さらにはKRから始まるすべてのCコードをコンパイルすることです。これは多くのオプション制限がある理由です。現代のコードスタイルのプロジェクトでは、厳密に準拠したモードが有効になります。

標準ではCの定義方法がありますが、実際にはCの使用方法があります。だから、コンパイラは単純にコードの作成を拒むことはできません。

開発者はポータブルで厳密に準拠したコードに移行していますが、C言語が初めて登場したときには本当に驚くほど強力なアセンブラのように少し使用されていました。当時のプログラムは、ほとんどの場合、一度に1つのアーキテクチャ用に書かれていました。

+1

もちろん、gccの作者は、厳密には合致しないコードに適合する場合、たとえ同じプラットフォーム用の他のコンパイラでも厳密に準拠したコードでは達成できない有用な振る舞い。 – supercat

関連する問題