私は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<1000
、j/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
問題ありません (ただし、あまり役に立ちません)。