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

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

8
C ++ 11は、標準化されたメモリモデルを導入しました。どういう意味ですか?そして、それはC ++プログラミングにどのように影響しますか?
C ++ 11は標準化されたメモリモデルを導入しましたが、それは正確にはどういう意味ですか?そして、それはC ++プログラミングにどのように影響しますか? この記事(Herb Sutterを引用しているGavin Clarkeによる)は、 メモリモデルとは、C ++コードに、だれがコンパイラを作成したか、どのプラットフォームで実行しているかに関係なく、標準ライブラリが呼び出されるようになったことを意味します。さまざまなスレッドがプロセッサのメモリと通信する方法を制御する標準的な方法があります。 「標準にある異なるコア間で[コード]を分割することについて話しているときは、メモリモデルについて話している。人々がコードで行う次の仮定を破ることなく、メモリモデルを最適化する」とSutterは述べた。 まあ、私はこれとオンラインで利用可能な同様の段落を覚えることができます(私は誕生時から自分の記憶モデルを持っているので:P)。他の人からの質問への回答として投稿することもできますが、正直なところ、私は正確に理解できませんこの。 C ++プログラマーは以前にもマルチスレッドアプリケーションを開発していたのですが、POSIXスレッド、Windowsスレッド、C ++ 11スレッドのどれが重要なのでしょうか。メリットは何ですか?低レベルの詳細を理解したいと思います。 また、C ++ 11のメモリモデルは、C ++ 11のマルチスレッドサポートに何らかの形で関連していると感じています。もしそうなら、正確にはどうですか?なぜそれらを関連付ける必要があるのですか? マルチスレッドの内部がどのように機能するのか、および一般的にメモリモデルが何を意味するのかわからないので、これらの概念を理解してください。:-)

5
CSS Flexboxに「justify-items」と「justify-self」プロパティがないのはなぜですか?
フレックスコンテナーの主軸と交差軸を考えます。 出典:W3C 主軸に沿ってフレックスアイテムを配置するには、1つのプロパティがあります。 justify-content クロス軸に沿ってフレックスアイテムを配置するには、3つのプロパティがあります。 align-content align-items align-self 上の画像では、主軸は水平で、交差軸は垂直です。これらは、フレックスコンテナのデフォルトの方向です。 ただし、これらの方向はflex-direction宿泊施設と簡単に交換できます。 /* main axis is horizontal, cross axis is vertical */ flex-direction: row; flex-direction: row-reverse; /* main axis is vertical, cross axis is horizontal */ flex-direction: column; flex-direction: column-reverse; (交差軸は常に主軸に対して垂直です。) 軸の働きを説明する上での私のポイントは、どちらの方向にも特別なものは何もないように見えることです。主軸、交差軸、重要度の点で同じであり、flex-direction簡単に前後に切り替えることができます。 では、なぜ交差軸は2つの追加の配置プロパティを取得するのですか? なぜされているalign-contentとalign-items主軸のために一つの特性に統合? 主軸がjustify-selfプロパティを取得しないのはなぜですか? これらのプロパティが役立つシナリオ: フレックスコンテナーの隅にフレックスアイテムを配置する #box3 { align-self: flex-end; justify-self: …


20
int a [] = {1,2、}; 奇妙なカンマが許可されています。何か特別な理由は?
多分私はこの惑星の出身ではないかもしれませんが、以下は構文エラーであるように思えます: int a[] = {1,2,}; //extra comma in the end しかし、そうではありません。このコードがVisual Studioでコンパイルされたときは驚きましたが、C ++のルールに関してはMSVCコンパイラを信頼しないことを学んだので、標準を確認しましたが、標準でも許可されています。あなたが私を信じないなら、あなたは文法規則のために8.5.1を見ることができます。 なぜこれが許可されるのですか?これは愚かな役に立たない質問かもしれませんが、なぜ私が尋ねているのか理解して欲しいのです。それが一般的な文法規則のサブケースである場合、私は理解するだろう-彼らは、初期化子リストの末尾に冗長なコンマを許可しないために、一般的な文法をこれ以上難しくしないことに決めました。ただし、追加のコンマは明示的に許可されています。たとえば、関数呼び出しの引数リストの最後に冗長なコンマを含めることはできません(関数がを受け取る場合...)。これは正常です。 繰り返しますが、この冗長なコンマが明示的に許可されている特別な理由はありますか?


12
メインは有効なJava識別子ですか?
私の子供たちの1人は高校でJavaを取り入れており、彼のテストの1つでこれを体験しました。 Javaで有効な識別子は次のうちどれですか? a。 123java b。 main c。 java1234 d。 {abce e。 )whoot 彼はbと答え、それを間違えた。 私は質問を見て、それmain は有効な識別子であり、正しいはずだったと主張しました。 識別子のJava 仕様を調べたところ、その点が強化されました。またmain、メソッドと同様に、という変数を持つサンプルプログラムも作成しました。彼は、Javaドキュメンテーションリファレンス、テストプログラム、および教師を含む反論を書面で作成し、それを無視して、答えはまだ正しくないと述べています。 あるmain有効な識別子?

11
なぜf(i = -1、i = -1)が未定義の動作なのですか?
私は評価違反の順序について読んでいて、私を困惑させる例を示しています。 1)スカラーオブジェクトの副作用が同じスカラーオブジェクトの別の副作用と比較してシーケンスされていない場合、動作は未定義です。 // snip f(i = -1, i = -1); // undefined behavior このコンテキストでiは、は明らかにスカラーオブジェクトです。 算術型(3.9.1)、列挙型、ポインター型、メンバー型へのポインター(3.9.2)、std :: nullptr_t、およびこれらの型のcv修飾バージョン(3.9.3)は、まとめてスカラー型と呼ばれます。 その場合、ステートメントがどのようにあいまいであるかはわかりません。最初または2番目の引数が最初に評価されるかどうかに関係なく、i最終的に-1、および両方の引数もであるように思え-1ます。 誰かが明確にしてもらえますか? 更新 私はすべての議論に本当に感謝しています。これまでのところ、@ harmicの回答は非常に気に入っています。一見しただけではわかりやすいにもかかわらず、このステートメントを定義する際の落とし穴と複雑さを明らかにしているからです。@ acheong87は、参照を使用するときに発生するいくつかの問題を指摘していますが、これは、この質問のシーケンスされていない副作用の側面とは直交していると思います。 概要 この質問はかなりの注目を集めたので、主なポイント/回答を要約します。まず、少し補足して、「なぜ」は密接に関連しているが微妙に異なる意味を持つ可能性があることを指摘します。つまり、「原因」、「理由」、および「目的」です。私は、答えが「なぜ」のそれらの意味のどれに対処したかによってグループ分けします。 何のために ここでの主な答えは、Paul Draperからのもので、Martin Jが同様の貢献をしましたが、それほど広くはありません。ポール・ドレイパーの答えは要約されます 動作が定義されていないため、未定義の動作です。 答えは、C ++標準の内容を説明するという点で、全体的に非常に優れています。また、f(++i, ++i);やなど、UBのいくつかの関連するケースも扱いますf(i=1, i=-1);。関連する最初のケースでは、最初の引数が必要かどうかi+1、2番目の引数が必要かどうか、i+2またはその逆が明確ではありません。2番目でiは、関数呼び出しの後に1か-1 かが明確ではありません。これらのケースはどちらも次のルールに該当するため、UBです。 スカラーオブジェクトの副作用が同じスカラーオブジェクトの別の副作用と比較してシーケンスされていない場合、動作は未定義です。 したがって、f(i=-1, i=-1)プログラマの意図が(IMHO)明白で明確であるにもかかわらず、同じ規則に該当するため、UBもです。 ポール・ドレイパーはまた、彼の結論でそれを明確にしています 動作が定義されているのでしょうか?はい。定義されましたか?番号。 「どのような理由/目的がf(i=-1, i=-1)未定義の動作として残されたのか?」 どのような理由/目的で C ++標準にはいくつかの見落とし(多分不注意)がありますが、多くの省略は十分な理由があり、特定の目的を果たします。目的は「コンパイラライターの仕事を簡単にする」または「コードを高速にする」のいずれかであることが多いことは承知していますが、主に UBのままにする正当な理由があるかどうかを知りたいと思っていましたf(i=-1, i=-1) 。 harmicとsupercatは、UBの理由を提供する主な答えを提供します。Harmicは、見かけ上アトミックな割り当て操作を複数の機械語命令に分割する可能性のある最適化コンパイラーと、それらの命令をさらにインターリーブして最適な速度にする可能性があることを指摘しています。これはいくつかの非常に驚くべき結果につながる可能性があります:i彼のシナリオでは-2になります!したがって、harmicは、操作がシーケンスされていない場合に、変数に同じ値を複数回割り当てると悪影響を与える可能性があることを示しています。 supercatは、本来あるf(i=-1, …

8
有効ですが、スイッチケースの価値のない構文?
少しタイプミスをして、私は誤ってこの構成を見つけました: int main(void) { char foo = 'c'; switch(foo) { printf("Cant Touch This\n"); // This line is Unreachable case 'a': printf("A\n"); break; case 'b': printf("B\n"); break; case 'c': printf("C\n"); break; case 'd': printf("D\n"); break; } return 0; } と思われるprintfの一番上のswitch文が有効でなく、完全に到達不能です。 到達できないコードについての警告さえないまま、クリーンなコンパイルを取得しましたが、これは無意味なようです。 コンパイラはこれに到達できないコードとしてフラグを立てるべきですか? これは何か目的を果たしますか?

4
何がi = i ++ + 1; C ++ 17で合法?
未定義の動作を叫ぶ前に、これはN4659(C ++ 17)に明示的にリストされています i = i++ + 1; // the value of i is incremented まだN3337(C ++ 11) i = i++ + 1; // the behavior is undefined 何が変わったの? 私が収集できるものから、[N4659 basic.exec]から 特に明記されていない限り、個々の演算子のオペランドおよび個々の式の部分式の評価は、シーケンスされていません。[...]演算子のオペランドの値計算は、演算子の結果の値計算の前にシーケンスされます。メモリロケーションへの副作用が同じメモリロケーションへの別の副作用または同じメモリロケーションにあるオブジェクトの値を使用した値の計算に関連してシーケンスされておらず、それらが潜在的に並行していない場合、動作は未定義です。 どこ [N4659 basic.type]で値が定義されている 自明にコピー可能な型の場合、値の表現はオブジェクト表現のビットのセットであり、 あり、実装で定義された一連の値の1つの個別の要素であるvalueます。 から [N3337 basic.exec] 特に明記されていない限り、個々の演算子のオペランドおよび個々の式の部分式の評価は、順序付けされていません。[...]演算子のオペランドの値計算は、演算子の結果の値計算の前にシーケンスされます。スカラーオブジェクトの副作用が、同じスカラーオブジェクトの別の副作用または同じスカラーオブジェクトの値を使用した値の計算に関連してシーケンスされていない場合、動作は未定義です。 同様に、値は [N3337 basic.type]ます 自明にコピー可能な型の場合、値の表現は、オブジェクトで表現された一連のビットであり、実装で定義された一連の値の1つの個別の要素であるvalueを決定します。 それらは重要ではない同時実行性の言及を除いて同一であり、スカラーオブジェクトの代わりにメモリロケーションを使用します。 算術型、列挙型、ポインター型、メンバー型へのポインターstd::nullptr_t、およびこれらの型のcv修飾バージョンは、まとめてスカラー型と呼ばれます。 これは例には影響しません。 [N4659 expr.ass] …

6
C ++ 11、14、17、または20は、piの標準定数を導入しますか?
CとC ++のpiの数値にはかなりばかげた問題があります。私が知る限り、でM_PI定義されてmath.hいることは、どの規格でも要求されていません。 新しいC ++標準では、標準ライブラリに複雑な数学の多くが導入されました-双曲線関数、std::hermiteおよびstd::cyl_bessel_i、さまざまな乱数ジェネレータなど。 「新しい」標準のいずれかがパイの定数をもたらしましたか?そうでない場合-なぜですか?この複雑な数学はそれなしでどのように機能しますか? 私はC ++のpiに関する同様の質問を認識しています(それらは数年前のものであり、標準から古くなっています); 問題の現状を知りたいのですが。 なぜ C ++にはまだpi定数がないのに、もっと複雑な数学がたくさんあるのか、という理由にも非常に興味があります。 UPD:自分でpiを4 * atan(1)またはacos(1)またはdouble pi = 3.14として定義できることを知っています。承知しました。しかし、なぜ2018年に私はまだそれをしなければならないのですか?標準の数学関数はpiなしでどのように機能しますか? UPD2:2019年7月にケルンで開催されたC ++委員会のこの出張レポートによると、提案P0631(数学定数)がC ++ 20に受け入れられました。つまり、ついに標準ライブラリに数piが含まれるようになります!

4
操作は「false <true」で明確に定義されていますか?
C ++仕様は以下を定義していますか? ブール型パラメータの「小なり」演算子の存在。 4つのパラメーターの順列の結果? つまり、次の操作の結果は仕様で定義されていますか? false &lt; false false &lt; true true &lt; false true &lt; true 私のセットアップ(Centos 7、gcc 4.8.2)では、以下のコードは私が期待するものを吐き出します(Cの履歴でfalseを0として、trueを1として表す): false &lt; false = false false &lt; true = true true &lt; false = false true &lt; true = false ほとんどの(すべての)コンパイラーが同じ出力を出すと確信していますが、これはC ++仕様によって規定されていますか?または、難読化されていますが、仕様に準拠したコンパイラは、trueがfalseよりも小さいと判断できますか? #include &lt;iostream&gt; const char * s(bool a) { …

8
「while(1);」を最適化する C ++ 0x
更新されました、以下を参照してください! C ++ 0xを使用すると、コンパイラーが次のスニペットの「Hello」を出力できるようになる #include &lt;iostream&gt; int main() { while(1) ; std::cout &lt;&lt; "Hello" &lt;&lt; std::endl; } スレッドと最適化機能に関係しているようです。しかし、これは多くの人を驚かせる可能性があるようです。 許可するためにこれが必要だった理由について誰かが良い説明をしていますか?参考までに、最新のC ++ 0xドラフトは次のように述べています。6.5/5 forステートメントの場合のfor-init-statementの外側のループ ライブラリI / O関数を呼び出さない。 揮発性オブジェクトにアクセスまたは変更しない、および 同期操作(1.10)またはアトミック操作(29節)を実行しない 実装は終了すると想定できます。[注:これは、終了が証明できない場合でも、空のループの削除などのコンパイラ変換を可能にすることを目的としています。—エンドノート] 編集: この洞察に満ちた記事は、その標準テキストについて述べています 残念ながら、「未定義の動作」という言葉は使用されていません。ただし、標準で「コンパイラはPを想定している可能性があります」と記載されている場合は常に、not-Pプロパティを持つプログラムはセマンティクスが未定義であることを意味します。 それは正しいですか、コンパイラは上記のプログラムの「バイ」を出力することを許可されていますか? ここにはさらに洞察に満ちたスレッドがあります。これはCへの類似の変更に関するもので、上記のリンクされた記事を書いた人によって開始されました。他の有用な事実の中で、それらはC ++ 0xにも適用されると思われる解決策を提示します(更新:これはn3225ではもう機能しません-下記を参照してください!) endless: goto endless; コンパイラはループではなくジャンプなので、それを最適化することはできません。別の男はC ++ 0xとC201Xで提案された変更を要約します ループを書き込むことによって、プログラマがアサートされているいずれかのループは、可視挙動を有するもの(実行I / O、アクセス揮発性オブジェクト、または実行同期または原子操作)をしていること、 またはそれが最終的に終了すること。副作用のない無限ループを作成してその仮定に違反すると、コンパイラーに嘘をついてしまい、プログラムの動作は未定義になります。(運が良ければ、コンパイラーが警告するかもしれません。)この言語は、目に見える動作なしで無限ループを表現する方法を提供していません(提供していませんか?)。 2011年3月31日にn3225で更新:委員会はテキストを1.10 / 24に移動し、 実装は、すべてのスレッドが最終的に次のいずれかを実行すると想定する場合があります。 終了、 …

1
std :: vector :: erase()およびstd :: deque :: erase()での割り当てのコピー/移動
答えるの過程では別の質問を私が少し異なる文言につまずいたstd::vector::erase()とstd::deque::erase()。 これはC ++ 14が言っていることですstd::deque::erase([deque.modifiers]/4-6私の強調): 効果: ... 複雑さ:デストラクタへの呼び出しの数は消去された要素の数と同じですが、代入演算子の呼び出しの数の数は、消去された要素の前の要素の数と後の要素の数の小さい方以下です消去された要素。 スロー:コピーコンストラクター、移動コンストラクター、割り当て演算子、または移動割り当て演算子によって例外がスローされない限り、何も発生しません。T。 そして、これがstd::vector::erase([vector.modifiers]/3-5)について言っていることです: 効果: ... 複雑さ:のデストラクタはT、消去された要素の数と等しい回数と呼ばれますが、移動代入演算子はT、消去された要素の後のベクトル内の要素の数と等しい回数と呼ばれます。 スロー:のコピーコンストラクター、移動コンストラクター、割り当て演算子、または移動割り当て演算子によって例外がスローされない限り、何も起こりませんT。 ご覧のとおり、両方の例外仕様は同じですが、std::vector代入代入演算子が呼び出されることが明示されているためです。 以下のための要件もありますTされるようにMoveAssignableするためにerase()、両方との仕事にstd::vectorとはstd::deque(表100)が、これは移動代入演算子の存在を意味するものではありません。一つはコピー代入演算子を定義し、移動代入演算子を定義することはできませんが、このクラスの意志をであるMoveAssignable。 念のため、GCCとClangで確認しました。実際にstd::vector::erase()移動代入演算子がない場合は、コピー代入演算子を呼び出しstd::deque::erase()、同じことを行います(デモ)。 だから問題は、私は何かを逃したのか、またはこれは規格の(編集上の)問題なのか? 更新:LWGの問題#2477を 送信しました。

4
C ++ゼロ初期化-このプログラムの「b」が初期化されていないのに「a」が初期化されるのはなぜですか?
このスタックオーバーフローの質問に対する受け入れられた(そして唯一の)回答によると、 コンストラクタを定義する MyTest() = default; 代わりに、オブジェクトをゼロ初期化します。 次に、なぜ次のことをするのですか? #include &lt;iostream&gt; struct foo { foo() = default; int a; }; struct bar { bar(); int b; }; bar::bar() = default; int main() { foo a{}; bar b{}; std::cout &lt;&lt; a.a &lt;&lt; ' ' &lt;&lt; b.b; } この出力を生成します: 0 32766 定義されている両方のコンストラクタがデフォルトですか?正しい?また、PODタイプの場合、デフォルトの初期化はゼロ初期化です。 そして、この質問に対する受け入れられた答えによれば、 PODメンバーがコンストラクターでもC …

3
このコードは、sizeof()を使用せずに配列サイズをどのように決定するのですか?
Cのインタビューの質問をたどると、「sizeof演算子を使用せずにCで配列のサイズを見つける方法は?」という質問があり、次の解決策が見つかりました。動作しますが、理由はわかりません。 #include &lt;stdio.h&gt; int main() { int a[] = {100, 200, 300, 400, 500}; int size = 0; size = *(&amp;a + 1) - a; printf("%d\n", size); return 0; } 予想通り、5を返します。 編集:人々はこの答えを指摘しましたが、構文は少し異なります、すなわちインデックス方法 size = (&amp;arr)[1] - arr; どちらの質問も有効で、問題へのアプローチが少し異なると思います。多大な助けと徹底した説明をありがとうございました!

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