【问题标题】:How to manipulate the output stream directly? (Was: why it's not increment value of increment operator in case of assignment in c?)如何直接操作输出流? (是:为什么在 c 中赋值的情况下它不是增量运算符的增量值?)
【发布时间】:2013-05-12 18:59:14
【问题描述】:

我修复了this question 中的代码,以便编译:

#define text ();
#define return &argv;return
int *** emphasized () {
    static int x, *argv = &x, **xpp = &argv;
    puts("\r10 11 11");
    return &xpp;
}
int main (int argc, char *argv[]) {
  int a;
    int n = 10;
    printf("%d",n);
      n++;
    printf("%d",n);
     a = n++;
    printf("%d",n);***emphasized text***
    return 0;
}

在原来的问题中,提问者说:

输出= 10 11 11 为什么它不是第二个增量运算符中 n 的增量值

这就是为什么emphasized() 做了一些有趣的事情。我试图想出一种方法,让提问者的文字代码按照他/她所说的去做。为此,我将***emphasized text*** 视为源代码的一部分。

我的 问题是:如何更改 emphasized() 以便在不调用任何输出函数的情况下呈现 10 11 11 输出?我希望能观察到一种将printf() 呈现的输出更改为标准输出以添加空格但会破坏最后一个数字的方法。

由于这个问题被标记为混淆,如果解决方案涉及添加更多#defines,那就去吧。

【问题讨论】:

  • 是什么让您认为增量不会发生?如果是输出,那仅仅是因为 puts 调用的输出就是这样。
  • 为什么要删除#define printf(a,b) (void)0这一行?
  • @JohnBode:不需要它来获得观察到的输出。
  • @user315052:是的,你做到了;如果你再次运行程序,你将肯定得到不同的输出。
  • @JohnBode:如果重定向到文件,但如果在控制台上观察到则不会。

标签: c obfuscation


【解决方案1】:

n 递增到 12,但由于从未打印过 n,所以它的值无关紧要。

通过预处理器运行那个废话,你就会明白为什么了。

有一个#define 使所有printf 语句无效。

实际输出来自emphasized中的puts

【讨论】:

    【解决方案2】:

    这是原始代码:

    #define text ();
    #define printf(a,b) (void)0
    #define return &argv;return
    int *** emphasized () {
        static int x, *argv = &x, **xpp = &argv;
        puts("\r10 11 11");
        return &xpp;
    }
    int main (int argc, char *argv[]) {
      int a;
        int n = 10;
        printf("%d",n);
          n++;
        printf("%d",n);
         a = n++;
        printf("%d",n);***emphasized text***
        return 0;
    }
    

    这是经过预处理器运行后的代码:

    int *** emphasized () {
        static int x, *argv = &x, **xpp = &argv;
        puts("\r10 11 11");
        &argv;return &xpp;
    }
    int main (int argc, char *argv[]) {
      int a;
        int n = 10;
        (void)0;
          n++;
        (void)0;
         a = n++;
        (void)0;***emphasized ();***
        &argv;return 0;
    }
    

    请注意,printf 语句不会出现在预处理代码中;在此版本中,n 的值根本没有显示到控制台。输出来自emphasized 函数。

    【讨论】:

      【解决方案3】:

      n 增加了两次,并且它也被打印出来,正如你所期望的那样。

      但是text已经被#defined变成了一对括号和一个分号:();,而return&argv;return替换了

      所以代码

      ***emphasized text***
      return 0;
      

      变成:

      ***emphasized();***
      &argv;return 0;
      

      或稍微不那么奇怪的格式:

      ***emphasized();
      ***&argv;
      return 0;
      

      所以 printfs 完全按照他们将要执行的操作,然后调用 emphasized(),并使用 '\r' (回车,无换行)备份光标并打印出来你的 10 11 11。

      所有星号仅用于显示,取消引用指针但不使用结果。

      【讨论】:

        【解决方案4】:

        这是一个稍微不那么混淆的版本,它将每个printf() 调用重新映射到最终构建输出的东西,如原始提问者所述。它稍微简单一些,因为它没有定义愚蠢的emphasized() 函数。它还避免了不必要地取消引用 argv,以避免在 argc 为 0 的情况下出现未定义的行为。

        此版本还具有这样的特性,即如果从程序中删除 ***emphasized text*** 字符串,该程序也将像所描述的询问器那样运行。

        #include <stdio.h>
        #define printf(f,x) printf(x>11?"%d\n":"%d ", x>11?x-1:x);
        #define emphasized &argv;
        #define text if(0)
        #define return &argv;return
        int main (int argc, char *argv[]) {
          int a;
            int n = 10;
            printf("%d",n);
              n++;
            printf("%d",n);
             a = n++;
            printf("%d",n);***emphasized text***
            return 0;
        }
        

        【讨论】:

          猜你喜欢
          • 2013-03-17
          • 1970-01-01
          • 2013-08-04
          • 1970-01-01
          • 2011-06-15
          • 2016-12-04
          • 2012-06-18
          • 1970-01-01
          • 2020-05-14
          相关资源
          最近更新 更多