任务:打印从1到1000的数字,不使用任何循环或条件语句。不要只写printf()或cout语句1000次。

用C或c++怎么做呢?


当前回答

丑陋的C答案(每10的幂只展开一个堆栈帧):

#define f5(i) f(i);f(i+j);f(i+j*2);f(i+j*3);f(i+j*4)
void f10(void(*f)(int), int i, int j){f5(i);f5(i+j*5);}
void p1(int i){printf("%d,",i);}
#define px(x) void p##x##0(int i){f10(p##x, i, x);}
px(1); px(10); px(100);

void main()
{
  p1000(1);
}

其他回答

这个实际上编译为没有任何条件的程序集:

#include <stdio.h>
#include <stdlib.h>

void main(int j) {
  printf("%d\n", j);
  (&main + (&exit - &main)*(j/1000))(j+1);
}

编辑:添加了'&',因此它将考虑地址,从而避免指针错误。

上面的这个版本在标准C中,因为它不依赖于函数指针的算术:

#include <stdio.h>
#include <stdlib.h>

void f(int j)
{
    static void (*const ft[2])(int) = { f, exit };

    printf("%d\n", j);
    ft[j/1000](j + 1);
}

int main(int argc, char *argv[])
{
    f(1);
}
#include <stdio.h>
#include <stdlib.h>

void print(int n)
{
    int q;

    printf("%d\n", n);
    q = 1000 / (1000 - n);
    print(n + 1);
}

int main(int argc, char *argv[])
{
    print(1);
    return EXIT_SUCCESS;
}

它最终会停止:P

不懂足够的C(++)来写代码,但你可以使用递归而不是循环。为了避免这种情况,可以使用在第1000次访问后抛出异常的数据结构。例如,某种带有范围检查的列表,在每次递归时增加/减少索引。

从评论中判断,c++中似乎没有任何范围检查列表?

相反,你可以用1/n作为递归函数的参数,每次调用都减少1。从1000开始。DivisionByZero异常将停止递归

#include <boost/mpl/range_c.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/lambda/lambda.hpp>
#include <iostream>

int main()
{
  boost::mpl::for_each<boost::mpl::range_c<unsigned, 1, 1001> >(std::cout << boost::lambda::_1 << '\n');
  return(0);
}

到目前为止,由于堆栈溢出,有很多不正常的退出,但还没有堆,所以这里是我的贡献:

#include <cstdio>
#include <cstdlib>
#include <sys/mman.h>
#include <sys/signal.h>
#define PAGE_SIZE 4096
void print_and_set(int i, int* s)
{
  *s = i;
  printf("%d\n", i);
  print_and_set(i + 1, s + 1);
}
void
sigsegv(int)
{
  fflush(stdout); exit(0);
}
int
main(int argc, char** argv)
{
  int* mem = reinterpret_cast<int*>
    (reinterpret_cast<char*>(mmap(NULL, PAGE_SIZE * 2, PROT_WRITE,
                                  MAP_PRIVATE | MAP_ANONYMOUS, 0, 0)) +
     PAGE_SIZE - 1000 * sizeof(int));
  mprotect(mem + 1000, PAGE_SIZE, PROT_NONE);
  signal(SIGSEGV, sigsegv);
  print_and_set(1, mem);
}

这不是很好的实践,也没有错误检查(原因很明显),但我不认为这是问题的重点!

当然,还有许多其他不正常的终止选项,其中一些更简单:assert()、SIGFPE(我认为有人这样做了),等等。