ループや条件文なしで 1 から 1000 までを出力する C コードはどのように機能しますか? 質問する

ループや条件文なしで 1 から 1000 までを出力する C コードはどのように機能しますか? 質問する

私はCコードを見つけましたループや条件なしで1から1000までを出力します: しかし、どのように動作するのか分かりません。誰かコードを調べて各行を説明してもらえませんか?

#include <stdio.h>
#include <stdlib.h>

void main(int j) {
  printf("%d\n", j);
  (&main + (&exit - &main)*(j/1000))(j+1);
}

ベストアンサー1

そのようなコードを絶対に書かないでください。


の場合j<1000j/1000はゼロです (整数除算)。したがって、

(&main + (&exit - &main)*(j/1000))(j+1);

は以下と同等です:

(&main + (&exit - &main)*0)(j+1);

それは次のとおりです。

(&main)(j+1);

mainを呼び出しますj+1

の場合j == 1000、同じ行が次のように出力されます。

(&main + (&exit - &main)*1)(j+1);

つまり

(&exit)(j+1);

これでexit(j+1)プログラムは終了します。


(&exit)(j+1)これらはexit(j+1)本質的に同じものです - C99 §6.3.2.1/4 を引用します:

関数指定子は関数型を持つ式です。sizeof演算子のオペランドである場合を除いてまたは単項演算子&、型 " を持つ関数指定子関数の戻り値型「は、型「を持つ式に変換されます関数を返す型へのポインタ「」。

exitは関数指定子です。単項&アドレス演算子がなくても、関数へのポインタとして扱われます。( は&それを明示的に示しています。)

関数呼び出しについては§6.5.2.2/1以降で説明されています。

呼び出される関数を表す式は、型を持つものとする。関数へのポインタvoid を返すか、配列型以外のオブジェクト型を返します。

これは、exit(j+1)関数型から関数へのポインタ型への自動変換によって機能し、(&exit)(j+1)関数へのポインタ型への明示的な変換でも同様に機能します。

そうは言っても、上記のコードは準拠しておらず (main引数を 2 つ取るか、まったく引数を取らない)、&exit - &main§6.5.6/9 によれば未定義であると私は考えています。

2つのポインタを減算すると、両方とも同じ配列オブジェクトの要素を指すものとする、または配列オブジェクトの最後の要素の 1 つ後; ...

この追加は(&main + ...)それ自体有効であり、使用できる。もし§6.5.6/7 によれば、追加された量はゼロである。

これらの演算子の目的では、配列の要素ではないオブジェクトへのポインターは、オブジェクトの型を要素型とする長さ 1 の配列の最初の要素へのポインターと同じように動作します。

したがって、にゼロを追加しても&main問題ありません (ただし、あまり役に立ちません)。

おすすめ記事