[c] 루프 나 조건문없이 1부터 1000까지 인쇄하는 C 코드는 어떻게 작동합니까?

루프 또는 조건부없이 1에서 1000까지 인쇄하는C 코드를 찾았습니다 .하지만 작동 방식을 이해하지 못합니다. 누구나 코드를 살펴보고 각 줄을 설명 할 수 있습니까?

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

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



답변

그런 코드를 작성하지 마십시오.


를 들어 j<1000, j/1000영 (정수 나눗셈)이다. 그래서:

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

다음과 같습니다.

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

어느 것이 :

(&main)(j+1);

어느 전화 mainj+1.

인 경우 j == 1000다음과 같은 줄이 나타납니다.

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

끓는점

(&exit)(j+1);

어느 것이 exit(j+1)프로그램을 떠난다.


(&exit)(j+1)과는 exit(j+1)본질적으로 같은 것입니다 – C99을 인용 §6.3.2.1 / 4 :

함수 지정자는 함수 유형이있는 표현식입니다. sizeof 연산자 또는 단항 & 연산자 의 피연산자 인 경우를 제외하고 , ” function returning type ” 유형의 함수 지정자는 ” function returning type 에 대한 포인터 “유형의 표현식으로 변환됩니다 .

exit함수 지정자입니다. 단항 &주소 연산자가 없어도 함수에 대한 포인터로 취급됩니다. ( &그냥 명시 적으로 만듭니다.)

함수 호출은 §6.5.2.2 / 1 및 다음에 설명되어 있습니다.

호출 된 함수를 나타내는 표현식은 void를 반환하거나 배열 유형 이외의 객체 유형을 반환하는 함수에 대한 유형 포인터를 가져야 합니다.

따라서 exit(j+1)함수 유형을 포인터 대 함수 유형으로 자동 변환하기 때문에 작동하며 포인터 대 함수 유형 (&exit)(j+1)으로의 명시 적 변환과 함께 작동합니다.

즉, 위의 코드는 일치하지 않으며 ( main두 가지 주장을 취하거나 전혀 고려하지 않음) &exit - &main§6.5.6 / 9에 따라 정의되지 않았습니다.

두 개의 포인터를 빼면 둘 다 같은 배열 객체의 요소를 가리 키 거나 하나는 배열 객체의 마지막 요소를 지나야합니다. …

추가는 (&main + ...)그 자체로 유효한 것, 그리고 사용할 수있는 경우 양이 영 (0)이 추가 §6.5.6 / 7 말한다 이후 :

이러한 연산자의 목적 상, 배열의 요소가 아닌 객체에 대한 포인터는 객체 유형을 요소 유형으로하여 길이가 1 인 배열의 첫 번째 요소에 대한 포인터와 동일하게 동작합니다.

따라서 0을 추가하면 &main괜찮을 것입니다 (그러나 많이 사용하지는 않음).


답변

재귀, 포인터 산술을 사용하고 정수 나누기의 반올림 동작을 이용합니다.

j/1000용어는 모두 0으로 내림합니다 j < 1000. 일단 j도달하면 (1000)는 1로 평가.

지금 당신이있는 경우 a + (b - a) * n, 여기서 n0 또는 1, 당신은으로 끝날 a경우 n == 0, 그리고 b경우 n == 1. 사용 &main(주소 main())와 &exit대한 ab용어 (&main + (&exit - &main) * (j/1000))수익률 1000 이하를 , 그렇지. 그런 다음 결과 함수 포인터에 인수가 제공 됩니다.&mainj&exitj+1

이 전체 구조는 재귀 동작을 초래 j합니다. 1000 미만인 동안 main재귀 적으로 호출됩니다. 때 j1000에 도달, 그것을 호출 exit종료 코드 1001로 프로그램 종료하고, 대신 (종류 더러운이지만, 작품).


답변