如何在C code,它从1打印到1000没有循环或条件语句工作? [英] How does the C code that prints from 1 to 1000 without loops or conditional statements work?

查看:104
本文介绍了如何在C code,它从1打印到1000没有循环或条件语句工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现 C code的<一个href=\"http://stackoverflow.com/questions/4568645/printing-1-to-1000-without-loop-or-conditionals/4583502#4583502\">prints从1到1000,而不循环或条件的:
但我不明白它是如何工作的。任何人都可以顺利通过code和解释每行?

 的#include&LT;&stdio.h中GT;
#包括LT&;&stdlib.h中GT;无效的主要(诠释J){
  的printf(%d个\\ N,J);
  (安培;主+(安培;出口 - &安培;主)*(J / 1000))(J + 1);
}


解决方案

永远不要写code类的。


有关 J&LT; 1000 焦耳/ 1000 是零(整数除法)。所以:

 (安培;主+(安培;出口 - &安培;主)*(J / 1000))(J + 1);

相当于:

 (安培;主+(安培;出口 - &安培;主)* 0)(J + 1);

这是:

 (安培;主)(J + 1);

其中要求 J + 1

如果Ĵ== 1000 ,那么同样的思路出来的:

 (安培;主+(安培;出口 - &安培;主)* 1)(J + 1);

这可以归结为

 (安培;出口)(J + 1);

这是退出(J + 1)并保留节目。


(安培;出口)(J + 1)退出(J + 1)基本上是相同的东西 - 报价C99§6.3.2.1/ 4:


  

一个函数标志是具有函数型的前pression。除非它是
  sizeof操作符的操作数的或一元和放大器;运营商的,功能与标志
  键入函数返回类型转换为具有输入指向一个前pression
  函数返回类型


退出是函数标志。即使没有一元&安培; 地址的运营商,它被视为一个函数指针。 (在&放大器; 只是使它显式)

和函数调用在§6.5.2.2/ 1和描述如下:


  

这表示调用的函数应具有类型前pression 函数指针返回void或大于一个数组类型返回其他的对象类型。


所以退出(J + 1)工作,因为函数类型的指针到函数类型的自动转换,而( &安培;出口)(J + 1)的作品,以及用显式转换为指针,以功能型

话虽这么说,上面的code为不符合(从以下两个参数或根本没有),而&安培;退出 - &放大器;主根据§6.5.6/ 9,我相信,不确定的:


  

当两个指针相减,应都指向同一个数组对象,或者一个过去的数组对象的最后一个元素的元素; ...


加法(&放大器;主+ ...)将本身有效的,并且可以使用,如果的量加入是零,因为§6.5.6/ 7说:


  

有关这些操作符的目的,一个指向的对象是不是一个一个元件
  阵列的行为相同的指针长度的一个的阵列与第一元件
  类型对象作为其元素的类型。


所以加入零到&放大器;主将是确定(但没有太大用处)

I've found C code that prints from 1 to 1000 without loops or conditionals : But I don't understand how it works. Can anyone go through the code and explain each line?

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

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

解决方案

Don't ever write code like that.


For j<1000, j/1000 is zero (integer division). So:

(&main + (&exit - &main)*(j/1000))(j+1);

is equivalent to:

(&main + (&exit - &main)*0)(j+1);

Which is:

(&main)(j+1);

Which calls main with j+1.

If j == 1000, then the same lines comes out as:

(&main + (&exit - &main)*1)(j+1);

Which boils down to

(&exit)(j+1);

Which is exit(j+1) and leaves the program.


(&exit)(j+1) and exit(j+1) are essentially the same thing - quoting C99 §6.3.2.1/4:

A function designator is an expression that has function type. Except when it is the operand of the sizeof operator or the unary & operator, a function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type".

exit is a function designator. Even without the unary & address-of operator, it is treated as a pointer to function. (The & just makes it explicit.)

And function calls are described in §6.5.2.2/1 and following:

The expression that denotes the called function shall have type pointer to function returning void or returning an object type other than an array type.

So exit(j+1) works because of the automatic conversion of the function type to a pointer-to-function type, and (&exit)(j+1) works as well with an explicit conversion to a pointer-to-function type.

That being said, the above code is not conforming (main takes either two arguments or none at all), and &exit - &main is, I believe, undefined according to §6.5.6/9:

When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; ...

The addition (&main + ...) would be valid in itself, and could be used, if the quantity added was zero, since §6.5.6/7 says:

For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

So adding zero to &main would be ok (but not much use).

这篇关于如何在C code,它从1打印到1000没有循环或条件语句工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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