当前位置: 首页 > 知识库问答 >
问题:

理解一个不常见的论点

郑光济
2023-03-14

以下问题是在一次大学编程竞赛中提出的。我们被要求猜测输出和/或解释其工作原理。不用说,我们都没有成功。

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

一些简短的谷歌搜索引导我找到了这个问题,在codegolf中被问到。stackexchange。com:

https://codegolf.stackexchange.com/a/1336/4085

在那里,它解释了它的作用:反转标准输入法并放置在标准输出上,但没有解释如何。

我在这个问题上也找到了一些帮助:main的三个参数和其他模糊技巧,但它仍然没有解释如何main(_)

我的问题是,这些语法是如何工作的?它们是我应该知道的吗,比如,它们仍然相关吗?

如果没有明确的答案,我将非常感谢您提供任何(指向资源链接等)的提示。


共有2个答案

姚星腾
2023-03-14

好的,\uu只是在早期K中声明的一个变量

程序将尝试从标准输入中读取一个字节。如果有输入,它将递归调用main继续读取一个字节。

在输入结束时,read(2)将返回0,表达式将返回0,将执行write(2)系统调用,调用链可能会展开。

我在这里说“可能”,因为从这一点上看,结果高度依赖于实现。写入(2)的其他参数缺失,但寄存器和堆栈中会有一些内容,因此会将一些内容传递到内核。相同的未定义行为适用于各种递归激活main的返回值。

在我的x86_64 Mac上,程序读取标准输入,直到EOF,然后退出,什么也不写。

严修谨
2023-03-14

这个程序做什么?

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)。因此,如果省略返回语句,返回值很可能是最近返回的函数。

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

对读取的调用或多或少是明显的:它从标准in(文件描述符0)读取到位于

<代码>

在这种情况下,右侧调用不带参数的main。在使用1个参数声明后不带参数调用main是未定义的行为。尽管如此,它通常有效,只要您不关心argc参数的初始值。

<代码>

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

嗯。快速查看手册页可以发现,write需要三个参数,而不是一个。另一种未定义的行为。就像用太少的参数调用main一样,我们无法预测write的第二个和第三个参数将收到什么。在典型的计算机上,他们会得到一些东西,但我们不能确定是什么。(在非典型计算机上,可能会发生奇怪的事情。)作者依赖于接收以前存储在内存堆栈上的内容。而且,他依赖于这是阅读的第二和第三个论点。

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

这个程序在许多计算机上都无法正常工作。即使您使用与原作者相同的计算机,它也可能无法在不同的操作系统上工作。即使使用同一台计算机和同一个操作系统,它也无法在许多编译器上工作。即使使用相同的计算机编译器和操作系统,如果更改编译器的命令行标志,也可能无法工作。

正如我在评论中所说,这个问题没有有效的答案。如果你发现一个竞赛组织者或竞赛评委有不同的说法,不要邀请他们参加你的下一次竞赛。

 类似资料:
  • 里面很多都是像 laterain 学习到的,如果能考上 cuit 的话,自动献菊花了。

  • 主要内容:1 概述,2 JUnit 4常用的注解,3 结论1 概述 在本文中,我们将讨论常用的注释,当您在类路径中包含junit4.jar时可用。 常用的注解是:   让我们用示例讨论每个注解。 2 JUnit 4常用的注解 2.1 @Before和@After 在Junit4中,没有setup() 或tearDown() 方法,相反,我们具有@Before和@After批注。通过使用@Before,可以将任何方法设置为setup(),通过使用@Afte

  • 本文向大家介绍C++常见异常处理原理及代码示例解析,包括了C++常见异常处理原理及代码示例解析的使用技巧和注意事项,需要的朋友参考一下 编程中常见的错误 程序的编译错误——比较好解决,主要是一些语法错误 程序的运行错误——产生因素较为复杂,如空间不够,下标越界,访问非法空间等。 异常是指程序运行时出现的不正常,可分为一下几类: CPU异常;如在计算过程中,出现除数为0的情况。 内存异常,如: 使用

  • 问1:INSERT/UPDATE/DELETE被解析为Query或DDL语句? 答1: 出现这类情况主要原因为收到的binlog就为Query事件,比如: binlog格式为非row模式,通过show variables like 'binlog_format'可以查看. 针对statement/mixed模式,DML语句都会是以SQL语句存在 mysql5.6+之后,在binlog为row模式下

  • 本页面罗列了大家使用 YApi 时遇到的常见问题. 如果没有找到您要的答案,请联系管理员. Q1 怎样联系组长? 组长分为 分组组长 和 项目组长: 分组组长:选择首页左侧的分组,点击右侧面板的 成员列表,成员右侧显示着 组长/开发者 的权限信息。 项目组长: 点击项目页的 设置 - 成员列表,成员右侧显示着 组长/开发者 的权限信息。 Q2 怎么快速迁移旧项目? 第一步. 使用 Chrome 浏

  • 译者:冯宝宝 我的模型报告“cuda runtime error(2): out of memory” 正如错误消息所示,您的GPU显存已耗尽。由于经常在PyTorch中处理大量数据,因此小错误会迅速导致程序耗尽所有GPU资源; 幸运的是,这些情况下的修复通常很简单。这里有一些常见点需要检查: 不要在训练循环中积累历史记录。 默认情况下,涉及需要梯度计算的变量将保留历史记录。这意味着您应该避免在计