タグ付けされた質問 「language-lawyer」

プログラミング言語と環境の正式または信頼できる仕様の複雑さについての質問。

7
Cでの配列の初期化に関する混乱
C言語で、次のように配列を初期化する場合: int a[5] = {1,2}; 明示的に初期化されていない配列のすべての要素は、ゼロで暗黙的に初期化されます。 しかし、私がこのような配列を初期化すると: int a[5]={a[2]=1}; printf("%d %d %d %d %d\n", a[0], a[1],a[2], a[3], a[4]); 出力: 1 0 1 0 0 わかりません、なぜ代わりにa[0]印刷1するの0ですか?未定義の動作ですか? 注:この質問はインタビューで尋ねられました。

4
null参照は可能ですか?
このコードは有効ですか(および定義された動作)? int &nullReference = *(int*)0; g ++および打ち鳴らす++使用する場合でも、警告なしにそれをコンパイルし、両方の-Wall、-Wextra、-std=c++98、-pedantic、-Weffc++... もちろん、参照にはアクセスできないため(nullポインターの逆参照を意味するため)、参照は実際にはnullではありませんが、アドレスをチェックすることで、nullかどうかを確認できます。 if( & nullReference == 0 ) // null reference

8
「else if」は単一のキーワードですか?
C ++は初めてです。以下のような条件文がよく見られます。 if statement_0; else if statement_1; 質問: 構文的にはelse if、単一のキーワードとして扱うべきですか?それとも実際には以下のようにif外側の入れ子になったステートメントelseですか? if statement_0; else if statement_1;

7
main関数の代わりにmainと呼ばれるグローバル変数を持つプログラムはどのように機能しますか?
次のプログラムを検討してください: #include <iostream> int main = ( std::cout << "C++ is excellent!\n", 195 ); Windows 7 OSでg ++ 4.8.1(mingw64)を使用すると、プログラムは正常にコンパイルおよび実行され、印刷されます。 C ++は素晴らしいです! コンソールに。main関数ではなくグローバル変数のように見えます。このプログラムを関数なしでどのように実行できますmain()か?このコードはC ++標準に準拠していますか?プログラムの動作は明確に定義されていますか?私も-pedantic-errorsオプションを使用しましたが、プログラムはまだコンパイルして実行されます。

2
「C ++プログラミング言語」第4版のセクション36.3.6のこのコードには、明確に定義された動作がありますか?
Bjarne StroustrupのC ++プログラミング言語の第4版セクションの36.3.6 STLに似た操作では、次のコードがチェーンの例として使用されています。 void f2() { std::string s = "but I have heard it works even if you don't believe in it" ; s.replace(0, 4, "" ).replace( s.find( "even" ), 4, "only" ) .replace( s.find( " don't" ), 6, "" ); assert( s == "I have heard it works …

8
実装定義の動作を回避する効率的な符号なしから符号付きのキャスト
unsigned intas引数を取り、intUINT_MAX +1を法とする合同を引数に返す関数を定義したいと思います。 最初の試みは次のようになります。 int unsigned_to_signed(unsigned n) { return static_cast<int>(n); } しかし、言語弁護士なら誰でも知っているように、INT_MAXより大きい値の符号なしから符号付きへのキャストは、実装によって定義されます。 (a)仕様で義務付けられている動作のみに依存するようにこれを実装したいと思います。(b)最新のマシンおよび最適化コンパイラでno-opにコンパイルされます。 奇妙なマシンに関しては... unsignedintに対してUINT_MAX + 1を法とするsignedint合同がない場合、例外をスローしたいとしましょう。複数ある場合(これが可能かどうかはわかりません)、最大のものが必要だとしましょう。 OK、2回目の試行: int unsigned_to_signed(unsigned n) { int int_n = static_cast<int>(n); if (n == static_cast<unsigned>(int_n)) return int_n; // else do something long and complicated } 私の謙虚な意見ではありそうもないので、私が典型的な2の補数システムを使用していないときは、効率についてはあまり気にしません。そして、私のコードが2050年の遍在する符号と大きさのシステムのボトルネックになった場合、誰かがそれを理解して最適化できるに違いありません。 さて、この2回目の試みは、私が望むものにかなり近いものです。キャスト先intは一部の入力に対して実装定義ですが、キャストバック先unsignedはUINT_MAX +1を法とする値を保持するために標準によって保証されています。したがって、条件付きは私が望むものを正確にチェックし、私が遭遇する可能性のあるどのシステムでもコンパイルされません。 ただし...int実装定義の動作を呼び出すかどうかを最初に確認せずに、まだキャストしています。2050年のいくつかの架空のシステムでは、誰が何を知っているかを実行できます。だから私はそれを避けたいとしましょう。 質問:私の「3回目の試み」はどのように見えるべきですか? 要約すると、私はしたい: unsignedintからsignedintにキャストします 値modUINT_MAX +1を保持します 標準で義務付けられている動作のみを呼び出す …


3
C ++では、型情報はいつ逆方向に流れますか?
私はちょうどでステファンT. Lavavejトークを見CppCon 2018に「クラステンプレート引数控除」、上のいくつかの点彼はついでに言います: C ++の型情報は、逆方向に流れることはほとんどありません... 1つまたは2つのケースがあるため、「ほとんど」と言わざるを得ませんでした。 彼がどのケースを参照しているのかを理解しようとしたにもかかわらず、私は何も思いつきませんでした。したがって、質問: C ++ 17標準では、その型情報が逆伝播するように義務付けられているのはどの場合ですか?

4
一部のコンパイラーが同一の文字列リテラルに同じアドレスを使用するのはなぜですか?
https://godbolt.org/z/cyBiWY 'some'MSVCによって生成されたアセンブラコードで2つのリテラルを確認できますが、clangとgccを使用するリテラルは1つだけです。これにより、コード実行の結果がまったく異なります。 static const char *A = "some"; static const char *B = "some"; void f() { if (A == B) { throw "Hello, string merging!"; } } 誰かがそれらのコンパイル出力の違いと類似点を説明できますか?最適化が要求されていないのに、clang / gccが何かを最適化するのはなぜですか?これはある種の未定義の動作ですか? また、宣言を以下に示すように変更すると、clang / gcc / msvcはアセンブラー"some"コードに何も残さないことに気づきました。なぜ動作が異なるのですか? static const char A[] = "some"; static const char B[] = "some";

3
いつ@classmethodを使用する必要があり、いつdef method(self)を使用する必要がありますか?
これまで使用したことのないDjangoアプリを統合しているときに、クラスで関数を定義するために使用される2つの異なる方法を見つけました。作者は両方とも非常に意図的に使用しているようです。最初のものは私自身がよく使うものです: class Dummy(object): def some_function(self,*args,**kwargs): do something here self is the class instance もう1つは、私が使用しないものです。これは主に、いつ使用するのか、何のために使用するのかがわからないためです。 class Dummy(object): @classmethod def some_function(cls,*args,**kwargs): do something here cls refers to what? Pythonのドキュメントでは、classmethodデコレータは次の文で説明されています。 クラスメソッドは、インスタンスメソッドがインスタンスを受け取るのと同じように、暗黙の最初の引数としてクラスを受け取ります。 したがって、私clsはDummyそれ自体を参照していると思います(classインスタンスではなく、)。私はいつでもこれを行うことができたので、なぜこれが存在するのか正確には理解していません: type(self).do_something_with_the_class これは明確にするためだけですか、それとも私は最も重要な部分を見逃しましたか?それなしでは実行できない不気味で魅力的なことですか?

2
演算子の優先順位以外に、余分な括弧はいつ効果がありますか?
C ++の括弧は多くの場所で使用されます。たとえば、関数の呼び出しやグループ化式で演算子の優先順位を上書きします。不正な余分な括弧(関数呼び出しの引数リストの周りなど)を除いて、C ++の一般的な(ただし絶対ではない)規則は、余分な括弧が害を及ぼすことはありません。 5.1一次式[expr.prim] 5.1.1一般[expr.prim.general] 6括弧で囲まれた式は、型と値が囲まれた式と同じである1次式です。括弧の存在は、式が左辺値かどうかには影響しません。括弧で囲まれた式は、別段の指示がない限り、囲まれた式を使用できるのとまったく同じコンテキストで、同じ意味で使用できます。 質問:基本的な演算子の優先順位を上書きする以外に、余分な括弧がC ++プログラムの意味を変更するのはどのコンテキストですか? 注:意味の異なる2つの構文を許可するのではなく、構文を制限するので、括弧なしのメンバーへのポインター構文の制限&qualified-idは範囲外と見なします。同様に、プリプロセッサマクロ定義内で括弧を使用すると、不要な演算子の優先順位を防ぐことができます。

2
非静的データメンバーとネストされたクラスコンストラクターのクラス内初期化を使用するときのエラー
次のコードは非常に些細なものであり、正常にコンパイルされるはずです。 struct A { struct B { int i = 0; }; B b; A(const B& _b = B()) : b(_b) {} }; このコードをg ++バージョン4.7.2、4.8.1、clang ++ 3.2および3.3でテストしました。このコードでg ++ 4.7.2 segfaultが発生するという事実(http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57770)を除いて、テスト済みの他のコンパイラーは、あまり説明のないエラーメッセージを出力します。 g ++ 4.8.1: test.cpp: In constructor ‘constexpr A::B::B()’: test.cpp:3:12: error: constructor required before non-static data member for ‘A::B::i’ has been …

3
これはC ++ 11 forループの既知の落とし穴ですか?
いくつかのメンバー関数で3つのdoubleを保持するための構造体があるとします。 struct Vector { double x, y, z; // ... Vector &negate() { x = -x; y = -y; z = -z; return *this; } Vector &normalize() { double s = 1./sqrt(x*x+y*y+z*z); x *= s; y *= s; z *= s; return *this; } // ... }; これは簡単にするために少し工夫されていますが、同様のコードがそこにあることに同意するはずです。これらのメソッドを使用すると、便利なチェーンを作成できます。次に例を示します。 Vector v …

3
プライベートコンストラクターがプライベートコンストラクターではないのはいつですか?
タイプがあり、そのデフォルトのコンストラクタをプライベートにしたいとします。私は次のように書きます: class C { C() = default; }; int main() { C c; // error: C::C() is private within this context (g++) // error: calling a private constructor of class 'C' (clang++) // error C2248: 'C::C' cannot access private member declared in class 'C' (MSVC) auto c2 = C(); // …

8
動作が未定義のブランチは到達不能と見なされ、デッドコードとして最適化されますか?
次のステートメントを検討してください。 *((char*)NULL) = 0; //undefined behavior 明らかに未定義の動作を引き起こします。特定のプログラムにそのようなステートメントが存在するということは、プログラム全体が未定義であること、または制御フローがこのステートメントにヒットしたときにのみ動作が未定義になることを意味しますか? 次のプログラムは、ユーザーが番号を入力しない場合に備えて明確に定義されています3か? while (true) { int num = ReadNumberFromConsole(); if (num == 3) *((char*)NULL) = 0; //undefined behavior } それとも、ユーザーが何を入力しても、完全に未定義の動作ですか? また、コンパイラは、未定義の動作が実行時に実行されないことを想定できますか?これにより、時間を遡って推論することができます。 int num = ReadNumberFromConsole(); if (num == 3) { PrintToConsole(num); *((char*)NULL) = 0; //undefined behavior } ここで、コンパイラーは、num == 3未定義の動作を常に呼び出す場合に備えて推論することができます。したがって、このケースは不可能でなければならず、番号を印刷する必要はありません。ifステートメント全体を最適化することができます。この種の後方推論は規格に従って許可されていますか?

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.