了解一种不常见的参数主要 [英] Understanding an uncommon argument to main

查看:101
本文介绍了了解一种不常见的参数主要的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的问题是在一所大学程序设计大赛给出。我们被要求猜测输出和/或解释其工作。不用说,我们没有成功。

The following question was given in a college programming contest. We were asked to guess the output and/or explain its working. Needless to say, none of us succeeded.

main(_){write(read(0,&_,1)&&main());}

一些简短的谷歌搜索使我这个确切的问题,在 codegolf.stackexchange.com 问:

<一个href=\"http://$c$cgolf.stackexchange.com/a/1336/4085\">http://$c$cgolf.stackexchange.com/a/1336/4085

有,其解释的什么的它:逆向标准输入和标准输出上的地方,但不是的如何的。

There, its explained what it does : Reverse stdin and place on stdout, but not how.

我还发现,在这个问题有所帮助:三个参数为主,和其他混淆技巧
但它仍然没有解释如何主(_)&放大器; _ &安培; &安培;主要()

I also found some help in this question : Three arguments to main, and other obfuscating tricks but it still does not explain how main(_), &_ and &&main() works.

我的问题是,如何的做这些语法工作?他们是什么,我应该知道,如,他们是否仍然适用?

My question is, how do these syntaxes work ? Are they something I should know about, as in, are they still relevant ?

我将不胜感激任何指针(到资源链接等),如果不是彻底的答案。

I would be grateful for any pointers (to resource links, etc.), if not outright answers.

推荐答案

这是什么节目呢?

main(_){write(read(0,&_,1)&&main());}

在我们分析它,让我们prettify是:

Before we analyze it, let's prettify it:

main(_) {
    write ( read(0, &_, 1) && main() );
}

首先,你应该知道, _ 是一个有效的变量名,虽然难看。让我们来改变它:

First, you should know that _ is a valid variable name, albeit an ugly one. Let's change it:

main(argc) {
    write( read(0, &argc, 1) && main() );
}

接着,认识到返回类型的功能,并且一个参数的类型在C任选(但不是在C ++中):

Next, realize that the return type of a function, and the type of a parameter are optional in C (but not in C++):

int main(int argc) {
    write( read(0, &argc, 1) && main() );
}

接下来,了解返回值是如何工作的。对于某些CPU型号,返回值总是存储在同一个寄存器(​​EAX在x86,例如)。因此,如果你省略了一个收益语句,返回值的可能的将是什么最新的功能恢复。

Next, understand how return values work. For certain CPU types, the return value is always stored in the same registers (EAX on x86, for example). Thus, if you omit a return statement, the return value is likely going to be whatever the most recent function returned.

int main(int argc) {
    int result = write( read(0, &argc, 1) && main() );
    return result;
}

要调用为更多或不太明显的:它从标准(文件描述符0)读取,到位于内存&安培; ARGC 1 字节。它返回 1 如果读取成功,否则为0。

The call to read is more-or-less evident: it reads from standard in (file descriptor 0), into the memory located at &argc, for 1 byte. It returns 1 if the read was successful, and 0 otherwise.

&放大器;&安培; 是逻辑与操作符。当且仅当它的左手侧是真(从技术上说,任何非零值),它评估其右手边。 &放大器;;在&安培的结果前pression是 INT 这始终是1(对于真)或0(假)。

&& is the logical "and" operator. It evaluates its right-hand-side if and only if it's left-hand-side is "true" (technically, any non-zero value). The result of the && expression is an int which is always 1 (for "true") or 0 (for false).

在这种情况下,右手边调用不带参数。调用与1参数声明后没有参数是未定义的行为。尽管如此,它往往工作,只要你不关心 ARGC 参数的初始值。

In this case, the right-hand-side invokes main with no arguments. Calling main with no arguments after declaring it with 1 argument is undefined behavior. Nevertheless, it often works, as long as you don't care about the initial value of the argc parameter.

&安培的结果;&安培; ,然后传递到的write()。所以,我们的code现在看起来像:

The result of the && is then passed to write(). So, our code now looks like:

int main(int argc) {
    int read_result = read(0, &argc, 1) && main();
    int result = write(read_result);
    return result;
}

嗯。快速浏览一下该男子页显示,有三个参数,没有之一。未定义行为的另一种情况。就像调用用过多的参数,我们不能predict什么将收到的第2和第3参数。在典型的电脑,他们将获得的的东西的,但我们不能肯定知道。 (非典型电脑,奇怪的事情都可能发生。)作者是在接收无论是pviously保存在存储堆栈上$ P $依托。并且,他将靠后的的作为第二和第三个参数来阅读。

Hmm. A quick look at the man pages reveals that write takes three arguments, not one. Another case of undefined behavior. Just like calling main with too few arguments, we cannot predict what write will receive for its 2nd and 3rd arguments. On typical computers, they will get something, but we can't know for sure what. (On atypical computers, strange things can happen.) The author is relying upon write receiving whatever was previously stored on the memory stack. And, he is relying upon that being the 2nd and 3rd arguments to read.

int main(int argc) {
    int read_result = read(0, &argc, 1) && main();
    int result = write(read_result, &argc, 1);
    return result;
}

杀青无效调用,并添加标题,并扩大了&放大器;&安培; 我们有:

Fixing the invalid call to main, and adding headers, and expanding the && we have:

#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;
}



结论

在多台计算机如预期该程序将无法正常工作。即使你使用同一台计算机作为原作者,它可能无法在不同的操作系统上工作。即使你使用同一台计算机和相同的操作系统,它不会很多编译器。即使你使用同一台计算机的编译器和操作系统,它可能不是如果你改变了编译器的命令行标志工作。

This program won't work as expected on many computers. Even if you use the same computer as the original author, it might not work on a different operating system. Even if you use the same computer and same operating system, it won't work on many compilers. Even if you use the same computer compiler and operating system, it might not work if you change the compiler's command line flags.

正如我在评论中说,这个问题并没有一个有效的答案。如果你发现了一个比赛组织者或竞赛法官,说否则,不邀请他们到你的下一个比赛。

As I said in the comments, the question does not have a valid answer. If you found a contest organizer or contest judge that says otherwise, don't invite them to your next contest.

这篇关于了解一种不常见的参数主要的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆