なぜi ++があるのか​​。私 - ; お互いの直後?


164

1997年にリリースされたnmapのソースコードを見ていたところ、コードのこのセクションが少し奇妙に見えました。

int i=0, j=0,start,end;
char *expr = strdup(origexpr);
ports = safe_malloc(65536 * sizeof(short));
i++;                                         /* <<<<<< */
i--;                                         /* <<<<<< */
for(;j < exlen; j++) 
  if (expr[j] != ' ') expr[i++] = expr[j]; 
expr[i] = '\0';

なぜあなたは持っているでしょうi++;し、次にi--;右のお互いの後に?iされ0、その後、i++ターンiします1。その後、i--ターンi0

元のソースコードへのリンク。検索する:

i++;
i--;

誰がこれが何のためにあるのか説明できますか?


25
作者に尋ねてください。
DaBler

8
私はそれらがいくつかの実験的またはデバッグ用コードの一部であったと思いますが、作者は後で削除するのを忘れていました。
Nate Eldredge

6
理由は明らかにあなたを混乱させることです、それが唯一の目的です:-)これがいくつかの古いコンパイラのコンパイラのバグを回避する小さな可能性があります。その場合、この理由を伝えるコメントがあったはずです。
gnasher729

18
@RingØ:1988年頃のgcc 1.27をgodboltで試してみました:godbolt.org/z/yYyFrQ。(最新のシステムヘッダーでは機能しないため、すべての標準ライブラリ関数を自分で宣言する必要がありました。)しかし、-O実際にはこれらのステートメントを最適化しています。
Nate Eldredge

21
これは、プログラマーが支払われた額を意味します...
TonyK

回答:


152

これはバグでした。これらの行は一緒iに変更されないため、そこにあるべきではありませんでした。

nmapを紹介したリンクされた記事は1997年9月1日に公開されました。https: //svn.nmap.org/nmapでnmapのSVNリポジトリを確認すると、1998年2月10日にチェックインされた最初のリビジョンにはこれらの行がありません。

int i=0, j=0,start,end;
char *expr = strdup(origexpr);
char *mem = expr;

ports = safe_malloc(65536 * sizeof(short));
for(;j < exlen; j++) 
  if (expr[j] != ' ') expr[i++] = expr[j]; 
expr[i] = '\0';

したがって、これは、最初のnmapソースコードの公開とSVNへの最初のチェックインの間に作成者が見つけて修正したものです。


1
そのページ<pre>にも記事の周りにタグがありません。Chromeのインスペクターは、それがDOM構築中にドキュメントのマングル化にどのようにつながるかを明らかにします;)
翼を持つ小惑星

4
それは読者を混乱させますが、それは完全に意図されたものではありません。明らかにバグだと思います。;-)
sergut

2
@sergutウィキペディアはあなたに同意しませんが、このブログ投稿は同意します、そして私も同様に傾向があります:-)
ToivoSäwén

4
さてi、intではなかったが、演算子のオーバーロードを伴ういくつかの派手なクラスである場合、これはいくつかの副作用をもたらす可能性があります(一般的にはコーディングの習慣が不十分である兆候です)。(もちろんこれがC ++の場合にのみ適用されます。)
Darrel Hoffman

5
いくつかのコンテキスト(メモリマップIO)では、変数を変更すると外部に影響が及ぶ可能性があることに注意してください。
nullromo

40

無駄だ。まったく何もしません。

私が推測するとしたら、それはおそらく開発中に使用されたいくつかのデバッグコードの残りです。

i++またはのいずれかが1 i--つの変更で導入され、もう1つは別の変更で導入されたと思います。

ただし、最初のソースリリースと最初のSVNリビジョンの間にリビジョン履歴がなかったため、導入のポイントを見つける方法はありません。


14
コードのデバッグに関する推測は正確だと思います。期待するブレークポイントを取得するためだけに、さまざまな種類のデバッグコードを見てきました。
Nathan Goings

9

非最適化コンパイラ、またはハードウェアの副作用を認識したコンパイラの場合は、i ++。i--シーケンスを使用すると、forループを通過してネストされたifに関係なく、iがメモリから読み取られてから再書き込みされます。

並列処理では、コードシーケンスがグローバルコピーではなく独自の変数のローカルコピーを使用するように、コンパイラのハッキングが行われることがあります。

この例はコードスニペットであるため、使用するコンパイラ、期待されるオペレーティングシステム/ハードウェア、および独立したスレッドとして実行可能なコードシーケンス/関数に含まれるかどうかを判断できません。

より単純なシステムでは、デバッグ環境でトラップ機能を実行するために、一時的に変数の変更を強制しました。その場合、開発者は開発が完了したときにコードを削除するのを忘れている可能性があります。


1
では、なぜそれを揮発性として宣言しないのですか?
vsz

6
iローカル変数としての宣言は上記のコードに示されていますが、i++; i--行がある場所で別のスレッドからアクセスできる方法はありません。
インタージェイ

@vsz私はむしろ彼iが不揮発性であることを余儀なくされていることを意味すると思います。ただし、CまたはC ++でのスレッド処理については扱っていませんi++; i--。そのため、どのように揮発性として扱うことができ、それをどのように抑制するかについてはわかりません。
エゴールハンス

volatileには、スレッドセーフ以外の目的があります。デバッグ中に使用して、コンパイラーが最適化しないようにすることもできます。
vsz

2

更新されたコードのみを確​​認することをお勧めします。(i = 2 + 1)の直後に(i-1)を使用しても意味がありません。iの値は変更されません。任意のcまたはc ++コンパイラを使用して試すことができます。または他の言語でも同じです。コンパイラーでコードを実行して、私が間違っているか正しいかを確認し、間違った答えをしている場合は知らせてください。

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