このプログラムは何をしますか?
main(_){write(read(0,&_,1)&&main());}
それを分析する前に、それをきれいにしましょう:
main(_) {
write ( read(0, &_, 1) && main() );
}
まず、_
醜い名前ではありますが、それが有効な変数名であることを知っておく必要があります。変更しましょう:
main(argc) {
write( read(0, &argc, 1) && main() );
}
次に、関数の戻り型とパラメーターの型がCではオプションであることに注意してください(C ++ではオプションではありません)。
int main(int argc) {
write( read(0, &argc, 1) && main() );
}
次に、戻り値がどのように機能するかを理解します。特定のCPUタイプの場合、戻り値は常に同じレジスタに格納されます(たとえば、x86のEAX)。したがって、return
ステートメントを省略すると、戻り値は最新の関数が返したものになる可能性があります。
int main(int argc) {
int result = write( read(0, &argc, 1) && main() );
return result;
}
toの呼び出しread
は、多かれ少なかれ明白です。標準のin(ファイル記述子0)から、にあるメモリにバイト単位で読み込まれ&argc
ます1
。1
読み取りが成功した場合は戻り、それ以外の場合は0を返します。
&&
論理「and」演算子です。左側が「true」(技術的にはゼロ以外の値)である場合にのみ、右側を評価します。&&
式の結果は、int
常に1(「true」の場合)または0(falseの場合)になります。
この場合、右側main
は引数なしで呼び出します。main
1つの引数で宣言した後、引数なしで呼び出すことは未定義の動作です。それでも、パラメータの初期値を気にしない限り、多くの場合機能しargc
ます。
次に、の結果が&&
に渡されwrite()
ます。したがって、コードは次のようになります。
int main(int argc) {
int read_result = read(0, &argc, 1) && main();
int result = write(read_result);
return result;
}
うーん。write
マニュアルページをざっと見ると、 1つではなく3つの引数を取ることがわかります。未定義動作の別のケース。main
引数が少なすぎる場合と同じようwrite
に、2番目と3番目の引数で何が返されるかを予測することはできません。一般的なコンピューターでは、何かを取得しますが、何が発生するかはわかりません。write
(非定型のコンピューターでは、奇妙なことが起こる可能性があります。)作成者は、以前にメモリスタックに格納されていたものをすべて受信することに依存しています。そして、彼はそれが2番目と3番目の引数であることに依存しています。
int main(int argc) {
int read_result = read(0, &argc, 1) && main();
int result = write(read_result, &argc, 1);
return result;
}
への無効な呼び出しを修正し、main
ヘッダーを追加して、次のように展開し&&
ます。
#include <unistd.h>
int main(int argc, int argv) {
int result;
result = read(0, &argc, 1);
if(result) result = main(argc, argv);
result = write(result, &argc, 1);
return result;
}
結論
このプログラムは、多くのコンピューターで期待どおりに機能しません。元の作成者と同じコンピューターを使用している場合でも、別のオペレーティングシステムでは動作しない可能性があります。同じコンピューターと同じオペレーティングシステムを使用している場合でも、多くのコンパイラーでは機能しません。同じコンピュータコンパイラとオペレーティングシステムを使用している場合でも、コンパイラのコマンドラインフラグを変更すると機能しない場合があります。
コメントで言ったように、質問には有効な答えがありません。コンテストの主催者または審査員が別の言い方をしているのを見つけた場合は、次のコンテストに招待しないでください。