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

这四行复杂C代码背后的概念

钱浩荡
2023-03-14

为什么这段代码给出输出C Suck?它背后的概念是什么?

#include <stdio.h>

double m[] = {7709179928849219.0, 771};

int main() {
    m[1]--?m[0]*=2,main():printf((char*)m);    
}

在这里测试。

共有3个答案

袁耀
2023-03-14

免责声明:此答案发布到问题的原始形式,其中仅提到C并包含一个C标题。问题转换为纯C是由社区完成的,没有来自原始提问者的输入。

从形式上讲,不可能对这个程序进行推理,因为它的格式不正确(即它不是合法的C)。它违反了C 11[basic.start.main]p3:

函数main不得在程序中使用。

撇开这一点不谈,它依赖于这样一个事实,即在典型的消费类计算机上,双精度编码是8字节长的,并且使用某种众所周知的内部表示。计算数组的初始值,以便在执行“算法”时,第一个双精度的最终值将使得内部表示(8字节)将是8个字符的ASCII码。然后,数组中的第二个元素是0.0,其第一个字节在内部表示中是0,使其成为有效的C样式字符串。然后使用printf()将其发送到输出。

在硬件上运行它,上面的一些不成立会导致垃圾文本(或者甚至可能是越界访问)。

呼延庆
2023-03-14

更可读的版本:

double m[2] = {7709179928849219.0, 771};
// m[0] = 7709179928849219.0;
// m[1] = 771;    

int main()
{
    if (m[1]-- != 0)
    {
        m[0] *= 2;
        main();
    }
    else
    {
        printf((char*) m);
    }
}

递归调用了771次。

开始时,m[0]=7709179928849219.0,代表C Suc; C。在每次调用中,m[0]都会加倍,以“修复”最后两个字母。在最后一次调用中,m[0]包含C Suck的ASCII字符表示,而m[1]仅包含零,因此它对C Suck字符串有一个空终止符。所有这些都假设m[0]存储在8个字节上,因此每个char占用1个字节。

如果没有递归和非法调用,调用它将如下所示:

double m[] = {7709179928849219.0, 0};
for (int i = 0; i < 771; i++)
{
    m[0] *= 2;
}
printf((char*) m);
冯元魁
2023-03-14

数字7709179928849219.0具有以下64位双精度二进制表示:

01000011 00111011 01100011 01110101 01010011 00101011 00101011 01000011
+^^^^^^^ ^^^^---- -------- -------- -------- -------- -------- --------

显示符号的位置;指数的^和尾数的-(即没有指数的值)。

由于表示使用二进制指数和尾数,因此将数字加倍会使指数增加1。您的程序精确地执行了771次,因此从1075开始的指数(10000110011的十进制表示)在末尾变得1075 771 = 1846;1846的二进制表示是11100110110。结果模式如下所示:

01110011 01101011 01100011 01110101 01010011 00101011 00101011 01000011
-------- -------- -------- -------- -------- -------- -------- --------
0x73 's' 0x6B 'k' 0x63 'c' 0x75 'u' 0x53 'S' 0x2B '+' 0x2B '+' 0x43 'C'

此图案对应于您看到的打印字符串,仅向后。同时,数组的第二个元素变为零,提供了空终止符,使字符串适合传递给printf()

 类似资料:
  • 问题内容: 我碰到了Java行,并对它的输出感到困惑。您能否解释一下此代码背后的逻辑 输出: 问题答案: 好吧,它等效于: 真正地将原始内容显式转换为只是使其调用而不是。 我相信to 转换 实际上首先 要进行隐式加宽转换-就像这样: 这些帮助有用?

  • 我知道嵌套for循环的时间复杂度等于最里面的循环执行的次数。 像外部循环从1到n的每个嵌套循环一样,它应该运行n次,但这里我们有,这使得算法运行的顺序更好。实际上,我在IDE中编写了这段代码,并在循环结束后打印了x的最终结果,对于不同的n值,我看到跳入内部for循环需要将近n倍的时间。 所以我认为这个算法的整个顺序是,但我不确定

  • 我被赋予以下任务: 给出了-2个列表。第一个列表的大小为N1,第二个列表的尺寸为N2。每个列表的元素不相同。编写一段代码,用第一个和第二个列表中的元素创建一个新列表。此列表也不应有相同的元素。还要估计代码的复杂性。 我编写了以下代码: 并假设 getNewList 方法的执行时间与 N1*N2 成正比。在回复中,我收到以下内容,没有任何解释 - “你错了,这段代码的复杂性不是 N1*N2”。 那么

  • 测量代码是否冗长的工具和度量 只是从远处看一眼乱七八糟四处蔓延的代码块,开发人员就会感到心惊肉跳 —— 这很正常!冗长的代码常常是复杂性的标志,会导致代码难以测试和维护。本月将学习三种测试代码复杂性的重要方法,它们分别基于方法长度、类长度和内部类耦合。在这一期的 追求代码质量 系列文章中,专家 Andrew Glover 将向您展示如何使用诸如 PMD 和 JavaNCSS 之类的工具,在您需要的