未定義のC ++の動作がCの定義された動作と一致するとどうなりますか?


10

*.cpp(Cコンパイラではなく)C ++でコンパイルするファイルがあります。含まれている関数は、Cで定義されているように見えるキャスト(最後の行を参照)に依存していますが(間違っている場合は修正してください!)、この特別な型のC ++ではありません。

[...] C++ code [...]

struct sockaddr_in sa = {0};
int sockfd = ...;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
bind(sockfd, (struct sockaddr *)&sa, sizeof sa);

[...] C++ code [...]

これをC ++ファイルでコンパイルしたので、これは現在定義済みまたは未定義の動作ですか?または*.c、これをファイルに移動して、動作を定義する必要がありますか?


1
ファイル拡張子は意味を持ちません。CまたはC ++としてコンパイルする場合のみ。
Fredrik、

1
対応する型は互いに継承されておらず、関係もありません。これはC ++では定義されていません
Daniel Stephens

1
通常、ファイルに.c拡張子がある場合、Cコンパイラは自動的に呼び出されます。
Igor R.

1
私はC ++コードでいつもそれをやっています。なぜうまくいかないのかわからない。どこかにヘッダーがありませんか?
user4581301

3
@DanielStephensこのプログラムは、ポインターを逆参照しようとすることはありません。キャスト自体が許可され、逆参照-場合によってのみ。C側がポインターを実際の型に正しくキャストし直した場合、すべてが正常です。これらの型の配置要件が異なる場合、キャストに関する問題が発生する可能性があります。
user7860670

回答:


6

これは、C ++とCの両方で定義されています。結果のポインタを逆参照しないため、厳密なエイリアス規則に違反していません。

これを可能にするC ++から引用(@interjayおよび@VTTに感謝)は次のとおりです。

オブジェクトポインターは、明示的に別の型のオブジェクトポインターに変換できます。

これを可能にするC引用(@StoryTellerに感謝)は次のとおりです。

オブジェクト型へのポインタは、別のオブジェクト型へのポインタに変換される場合があります。

これらは、1つのポインター型を別のポインター型に変換できる(そしてオプションで元に戻す)ことができることを指定しています。

そして、これはこの特定のケースを可能にするPOSIXから引用です:

sockaddr_in構造体は、インターネットアドレスファミリのアドレスを格納するために使用されます。この型へのポインターは、ソケット関数で使用するために、アプリケーションによってstruct sockaddr *にキャストされます。

この関数(bind)はC標準ライブラリの一部であるため、内部で行われる処理(具体的には、型キャストされたポインタの逆参照)の動作は未定義ではありません。


より一般的な質問に答えるには:

CとC ++は2つの異なる言語です。Cで定義されていてC ++では定義されていないものは、Cでは定義されていますが、C ++では定義されていません。2つの言語間の暗黙の互換性はそれを変更しません。Cで明確に定義されているがC ++では定義されていないコードを使用する場合は、Cコンパイラを使用してそのコードをコンパイルする必要があります。


1
@interjay標準からの引用でそれをバックアップできますか(CまたはC ++のどちらでも問題ありません)?
SS Anne、


1
@StoryTellerありがとう。代わりにHTTPバージョンを追加しました。
SS Anne、

2
間違いなく、これはPOSIX標準の欠陥です。2番目の引数bindはa const void *でなければなりませんが、C言語でのの存在(およびC ++の存在)bindよりも前から存在voidしています。彼らはを追加するためにある時点でそれを更新しましたconstが、基本的なタイプは修正していません。
クリス・ドッド

1
私はこの話をお勧めしますyoutube.com/watch?v=_qzMpk-22ccそれが答えを検証するかどうか、またはそれが実際に反対を言っているかどうかはまだわかりません:-o C ++は悪夢です..笑
ダニエルスティーブンス

-3

CとC ++コード間の呼び出しはすべて、それぞれの規格の観点から、未定義の動作を呼び出しますが、ほとんどのプラットフォームはそのようなことを指定します。

CまたはC ++標準の一部と実装のドキュメントが一緒にアクションを定義または説明しているが、他の部分がそれを未定義として特徴付けている状況では、実装は、顧客のニーズに最適な方法でコードを処理することが許可されています。顧客のニーズに無関心です-どんな方法でも彼らが合うと思います。標準がそのような問題を管轄外と見なしているという事実は、さまざまな目的への適合性を主張する実装がそれらを有意義に処理することが期待される時期および/または方法に関する判断を意味するものではありませんが、一部のコンパイラーメンテナーは、そうするという神話に同意しています。


最初の段落:「CおよびC ++コード間の呼び出しはすべて未定義の動作を呼び出します」「未定義の動作を呼び出す」などのことがあったとしても、これはまだ意味がありません。
オービットでの軽量レース、

2番目の段落:何を言おうとしているのかわからない。
オービットでの軽量レース、

@LightnessRacesinOrbitこの回答は、質問に[language-lawyer]タグを追加した結果だと思います。私はそれをよく考えて(答えは文字通り過ぎる傾向がある)、それを削除しました。
SSアン、

1
@ JL2210それはあなたのせいではなかったと思います。
オービットのライトネスレース
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.