C ++ 함수가 특정 변수의 값을 변경할 것인지 결정할 수있는 컴파일러를 빌드하는 것이 불가능한 이유는 무엇입니까?


104

나는 책에서이 줄을 읽었습니다.

실제로 C ++ 함수가 특정 변수의 값을 변경할지 여부를 결정할 수있는 컴파일러를 빌드하는 것은 불가능합니다.

이 단락은 const-ness를 확인할 때 컴파일러가 보수적 인 이유에 대해 이야기하고있었습니다.

왜 그런 컴파일러를 만드는 것이 불가능합니까?

컴파일러는 항상 변수가 재 할당되었는지, 상수가 아닌 함수가 호출되는지, 아니면 상수가 아닌 매개 변수로 전달되는지 확인할 수 있습니다.


24
가장 먼저 떠오르는 것은 동적 링크 라이브러리입니다. 내 컴퓨터에서 코드를 컴파일하고 컴퓨터에서 코드를 컴파일 하고 런타임에 링크하면 컴파일러가 변수를 수정했는지 여부를 어떻게 알 수 있습니까?
Mooing Duck 2013

4
@MooingDuck 정확히 이것입니다. 더 넓게 보면 컴파일러는 함수를 개별적으로 컴파일하지 않고 컴파일러의 범위 내에 있지 않을 수도있는 더 넓은 그림의 일부로 컴파일합니다.
called2voyage

3
"불가능"은 과장된 표현 일 수 있습니다. "계산적으로 실행 불가능"(NP-hard에서와 같이)이 더 나은 특성화 일 수 있지만 학생이 이해하기에는 조금 더 어렵습니다. 연결된 목록 또는 기타 추상 데이터 구조를 상상해보십시오. 목록 / 트리 / 무엇이든간에 하나의 노드를 변경하는 함수를 호출하면 컴파일러는 기본적으로 프로그램을 완전히 시뮬레이션하지 않고 어떤 노드가 수정되었는지 (그리고 더 중요한 것은 어떤 것이 수정되지 않았는지) 정확히 증명하기를 원할 수 있습니다. 예상 입력 3 일 복용 모든 동안은 ... 하나 개의 소스 파일을 컴파일합니다
twalberg

36
@twalberg Impossible은 과장된 것이 아니며 Halting 문제는 여러 답변이 설명하는 것처럼 여기에 적용됩니다. 일반 프로그램을 알고리즘 적으로 완전히 분석하는 것은 불가능합니다.
Fiktik

5
@twalberg 유효한 프로그램의 하위 집합 만 컴파일하는 컴파일러는 그다지 유용하지 않습니다.
Caleb

답변:


139

왜 그런 컴파일러를 만드는 것이 불가능합니까?

같은 이유로 주어진 프로그램이 종료되는지 여부를 결정하는 프로그램을 작성할 수 없습니다. 이것은 중지 문제 로 알려져 있으며 계산할 수없는 문제 중 하나입니다.

명확 하게 말하면 함수가 어떤 경우에 변수 변경하는지 확인할 수있는 컴파일러를 작성할 수 있지만 함수가 변수를 변경 (또는 중지) 할 것인지 여부를 안정적으로 알려주 는 컴파일러를 작성할 수 없습니다. 가능한 모든 기능.

다음은 간단한 예입니다.

void foo() {
    if (bar() == 0) this->a = 1;
}

컴파일러는 코드를보고 foo변경 여부 를 어떻게 결정할 수 a있습니까? 실행 여부는 함수 외부의 조건, 즉 bar. 중지 문제를 계산할 수 없다는 증거에는 그 이상이 있지만 연결된 Wikipedia 기사 (및 모든 계산 이론 교과서)에서 이미 잘 설명되어 있으므로 여기서 올바르게 설명하지 않겠습니다.


48
@mrsoltys, 양자 컴퓨터는 일부 문제에 대해 "단지"기하 급수적으로 빠르며 결정 불가능한 문제를 해결할 수 없습니다.
zch

8
@mrsoltys 인수 분해와 같은 기하 급수적으로 복잡한 알고리즘은 양자 컴퓨터에 적합하지만 문제 중지는 논리적 딜레마입니다. 어떤 종류의 "컴퓨터"를 가지고 있더라도 계산할 수 없습니다.
user1032613

7
@mrsoltys, 똑똑한 사람이 되려면 예, 바뀔 것입니다. 불행히도 알고리즘이 종료되고 여전히 실행 중임을 의미합니다. 안타깝게도 직접 ​​관찰하지 않고는 어떤 것이 실제 상태에 영향을 미치는지 알 수 없습니다.
Nathan Ernst

9
@ ThorbjørnRavnAndersen : 좋아, 그래서 내가 프로그램을 실행하고 있다고 가정하자. 종료 여부를 정확히 어떻게 결정합니까?
ruakh

8
@ ThorbjørnRavnAndersen 그러나 실제로 프로그램을 실행하고 종료하지 않으면 (예 : 무한 루프) 종료되지 않는다는 사실을 결코 알 수 없습니다. 마지막 하나 ...
MaxAxeHax

124

그러한 컴파일러가 존재한다고 상상해보십시오. 편의를 위해 전달 된 함수가 주어진 변수를 수정하면 1을 반환하고 함수가 수정하지 않으면 0을 반환하는 라이브러리 함수를 제공한다고 가정 해 보겠습니다. 그러면이 프로그램은 무엇을 인쇄해야합니까?

int variable = 0;

void f() {
    if (modifies_variable(f, variable)) {
        /* do nothing */
    } else {
        /* modify variable */
        variable = 1;
    }
}

int main(int argc, char **argv) {
    if (modifies_variable(f, variable)) {
        printf("Modifies variable\n");
    } else {
        printf("Does not modify variable\n");
    }

    return 0;
}

12
좋은! 나는 거짓말 쟁이의 역설이다 프로그래머에 의해 작성한다.
Krumelur

28
그것은 실제로 중단 문제의 결정 불가능성에 대한 유명한 증거의 멋진 적응 일뿐 입니다.
Konstantin Weitz

10
이 구체적인 경우 "modifies_variable"은 true를 반환해야합니다. 변수가 실제로 수정되는 실행 경로가 하나 이상 있습니다. 그리고 그 실행 경로는 외부의 비 결정적 함수를 호출 한 후에 도달하므로 전체 함수는 비 결정적입니다. 이 두 가지 이유로 컴파일러는 비관적 인 관점을 취하고 변수를 수정한다고 결정해야합니다. 결정적 비교 (컴파일러에 의해 확인 가능)가 거짓 (즉, "1 == 1")을 산출 한 후 변수 수정 경로에 도달하면 컴파일러는 해당 함수가 변수를 수정하지 않는다고 안전하게 말할 수 있습니다
Joe Pineda

6
@JoePineda : 문제는 f변수를 수정할 수 있는지 여부가 아니라 변수를 수정하는지 여부입니다. 정답입니다.
Neil G

4
@JoePineda : modifies_variable컴파일러 소스에서 코드를 복사 / 붙여 넣기하는 것을 막지 못해 인수를 완전히 무효화합니다. (오픈 소스로 가정하지만 요점은 분명해야 함)
orlp

60

"변수 를 수정하는 실행 경로가 있음 "" 이 입력이 주어지면 변수를 수정하거나 수정 하지 않을 것 "과 혼동하지 마십시오 .

전자는 불투명 한 술어 결정 이라고 하며 결정하기가 거의 불가능합니다. 중지 문제로 인한 감소를 제외하고는 입력이 알 수없는 소스 (예 : 사용자)에서 올 수 있음을 지적 할 수 있습니다. 이것은 C ++뿐만 아니라 모든 언어에 해당 됩니다.

그러나 후자의 명령문 은 모든 최적화 컴파일러가 수행하는 구문 분석 트리를 보면 확인할 있습니다. 그들이하는 이유는 순수 함수 (그리고 참조 적으로 투명 함의 일부 정의를 위한 참조 적으로 투명한 함수 ) 는 쉽게 inlinable하거나 컴파일 타임에 값을 결정하는 것과 같이 적용 할 수있는 모든 종류의 멋진 최적화를 가지고 있기 때문입니다. 그러나 함수가 순수한지 알기 위해서는 변수를 수정할 있는지 알아야 합니다.

따라서 C ++에 대한 놀라운 진술로 보이는 것은 실제로 모든 언어에 대한 사소한 진술입니다.


5
이것이 가장 좋은 대답입니다. 그 구별을하는 것이 중요합니다.
UncleZeiv

"사소한 불가능"?
Kip

2
@Kip "결정하기가 거의 불가능하다"는 것은 아마도 "결정하기 불가능하고 증거가 사소하다"는 뜻일 것입니다.
fredoverflow 2014 년

28

"C ++ 함수가 특정 변수의 값을 바꿀지 여부"의 핵심 단어는 "will"이라고 생각합니다. C ++ 함수 특정 변수의 값 변경할 있는지 여부를 확인하는 컴파일러를 빌드하는 것은 확실히 가능 합니다. 변경이 일어날 것이라고 확신 할 수는 없습니다.

void maybe(int& val) {
    cout << "Should I change value? [Y/N] >";
    string reply;
    cin >> reply;
    if (reply == "Y") {
        val = 42;
    }
}

"C ++ 함수가 특정 변수의 값을 변경할 수 있는지 여부를 확인하는 컴파일러를 만드는 것은 확실히 가능합니다."아니요, 그렇지 않습니다. Caleb의 답변을 참조하십시오. 컴파일러가 foo ()가 a를 변경할 수 있는지 알기 위해서는 bar ()가 0을 반환 할 수 있는지 알아야합니다. 그리고 계산 가능한 모든 함수의 가능한 모든 반환 값을 알 수있는 계산 가능한 함수는 없습니다. 따라서 컴파일러가 도달 여부를 알 수없는 코드 경로가 있습니다. 도달 할 수없는 코드 경로에서만 변수가 변경되면 변경되지 않지만 컴파일러는이를 감지하지 못합니다
Martin Epsz 2013

12
@MartinEpsz "can"은 "변경 가능"이 아니라 "변경 가능"을 의미합니다. 나는 이것이 OP가 const-ness 검사 에 대해 이야기 할 때 염두에 둔 것이라고 믿는다.
dasblinkenlight

@dasblinkenlight 나는 OP가 첫 번째, "변경 허용", 또는 "변경 가능 또는 변경 불가"대 "확실히 변경되지 않을 것"을 의미한다고 생각한다는 데 동의해야합니다. 물론 이것이 문제가 될 시나리오를 생각할 수 없습니다. 컴파일러를 수정하여 식별자가 포함 된 모든 함수 또는 "변경 가능"응답 속성이있는 함수 호출에 대해 "변경 가능"이라고 간단히 응답 할 수도 있습니다. 즉, C와 C ++는 사물에 대한 정의가 느슨하기 때문에 이것을 시도하기에는 끔찍한 언어입니다. 이것이 C ++에서 const-ness가 문제가되는 이유라고 생각합니다.
DDS

@MartinEpsz : "그리고 계산 가능한 함수의 가능한 모든 반환 값을 말할 수있는 계산 가능한 함수는 없습니다". "가능한 모든 반환 값"을 확인하는 것은 잘못된 접근 방식이라고 생각합니다. 방정식을 풀 수있는 수학 시스템 (maxima, mathlab)이 있습니다. 즉, 함수에 유사한 접근 방식을 적용하는 것이 합리적입니다. 즉, 미지수가 여러 개인 방정식으로 취급합니다. 문제는 흐름 제어 + 부작용 => 해결할 수없는 상황입니다. IMO (기능적 언어, 할당 / 부작용 없음) 없이는 어떤 경로 프로그램이 걸릴지 예측할 수 있었을 것입니다
SigTerm

16

주어진 함수가 특정 변수를 수정할지 여부를 컴파일 타임에 알고리즘 적으로 알 수 없다는 것을 설명하기 위해 중지 문제를 호출 할 필요가 없다고 생각합니다.

대신, 함수의 동작은 종종 컴파일러가 미리 알 수없는 런타임 조건에 의존한다는 점을 지적하는 것으로 충분합니다. 예

int y;

int main(int argc, char *argv[]) {
   if (argc > 2) y++;
}

컴파일러 y는 수정 여부를 어떻게 확실하게 예측할 수 있습니까?


7

이는 수행 될 수 있으며 컴파일러는 일부 함수에 대해 항상 수행합니다. 예를 들어 간단한 인라인 접근 자 또는 많은 순수 함수에 대한 사소한 최적화입니다.

불가능한 것은 일반적인 경우에 그것을 아는 것입니다.

시스템 호출이나 다른 모듈에서 오는 함수 호출 또는 잠재적으로 재정의 된 메서드에 대한 호출이있을 때마다 해커가 스택 오버플로를 사용하여 관련없는 변수를 변경하는 적대적인 인수를 포함하여 모든 일이 발생할 수 있습니다.

그러나 const를 사용하고, 전역을 피하고, 포인터에 대한 참조를 선호하고, 관련없는 작업에 대한 변수 재사용을 피해야합니다. 이렇게하면 공격적인 최적화를 수행 할 때 컴파일러의 수명이 더 쉬워집니다.


1
내가 올바르게 기억한다면 그것이 함수형 프로그래밍의 요점입니다. 맞죠? 순전히 결정적이며 부작용이없는 함수 만 사용함으로써 컴파일러는 공격적인 최적화, 사전 실행, 사후 실행, 메모 화 및 컴파일 시간에 실행까지 자유롭게 수행 할 수 있습니다. 많은 응답자가 무시하거나 혼란스러워하는 점 실제로 모든 프로그램의 잘 작동하는 하위 집합이 가능 하다는 것 입니다 . 그리고이 부분 집합은 사소하거나 흥미롭지 않습니다. 실제로 매우 유용합니다. 그러나 절대적인 일반적인 경우에는 실제로 불가능합니다.
Joe Pineda 2013

오버로딩은 컴파일 타임 개념입니다. 아마도 "무시 된 방법"을 의미했을 것입니다.
fredoverflow 2014 년

@FredOverflow : 예, 재정의를 의미합니다. 오버로딩은 실제로 컴파일 시간 개념입니다. 발견 해주셔서 감사합니다 (물론 구현이 다른 컴파일 유닛에서 나온다면 컴파일러는 여전히 그것을 분석하는 데 문제가있을 수 있지만 제가 의미 한 것은 아닙니다). 나는 답을 고칠 것이다.
kriss 2014 년

6

이를 설명하는 데는 여러 가지 방법이 있으며 그 중 하나는 중지 문제입니다 .

계산 가능성 이론에서 중단 문제는 "임의의 컴퓨터 프로그램에 대한 설명이 주어지면 프로그램 실행이 완료되는지 또는 계속 실행되는지 결정"과 같이 설명 할 수 있습니다. 이것은 프로그램과 입력이 주어지면 프로그램이 해당 입력으로 실행될 때 결국 중지 될 것인지 또는 영원히 실행될 것인지를 결정하는 문제와 동일합니다.

Alan Turing은 1936 년에 가능한 모든 프로그램 입력 쌍에 대한 정지 문제를 해결하는 일반적인 알고리즘이 존재할 수 없음을 증명했습니다.

다음과 같은 프로그램을 작성하면 :

do tons of complex stuff
if (condition on result of complex stuff)
{
    change value of x
}
else
{
    do not change value of x
}

x변화 의 가치가 있습니까? 이를 확인하려면 먼저 do tons of complex stuff부품으로 인해 조건이 발생하는지 여부를 확인해야합니다. 그것은 컴파일러가 할 수없는 일입니다.


6

정지 문제를 직접 사용하는 답이 없다는 사실에 정말 놀랐습니다! 이 문제에서 중단 문제로 매우 간단하게 줄일 수 있습니다.

컴파일러가 함수가 변수 값을 변경했는지 여부를 알 수 있다고 상상해보십시오. 그러면 프로그램의 나머지 부분에서 x 값이 모든 호출에서 추적 될 수 있다고 가정하면 다음 함수가 y 값을 변경하는지 여부를 확실히 알 수 있습니다.

foo(int x){
   if(x)
       y=1;
}

이제 우리가 좋아하는 프로그램에 대해 다음과 같이 다시 작성해 보겠습니다.

int y;
main(){
    int x;
    ...
    run the program normally
    ...
    foo(x);
}

프로그램이 y의 값을 변경하는 경우에만 종료됩니다. 종료하기 전에 foo ()가 마지막으로 수행하는 작업입니다. 이것은 우리가 중단 문제를 해결했음을 의미합니다!

위의 축소가 보여주는 것은 변수의 값이 변경되는지 여부를 결정하는 문제가 적어도 중단 문제만큼 어렵다는 것입니다. 중지 문제는 계산할 수없는 것으로 알려져 있으므로이 문제도 마찬가지입니다.


의 값을 변경하면 프로그램이 종료되는 이유에 대해 귀하의 추론을 따르는 지 잘 모르겠습니다 y. foo()빨리 돌아온 다음 main()나가는 것처럼 보입니다 . (또한, 당신은 foo()논쟁없이 전화 하고 있습니다 ... 그것은 내 혼란의 일부입니다.)
LarsH

1
@LarsH : 수정 된 프로그램이 종료되면 마지막으로 호출 한 함수는 f입니다. y가 수정 된 경우 f가 호출되었습니다 (다른 명령문은 수정에 의해서만 도입되었으므로 y를 변경할 수 없습니다). 따라서 y가 수정되면 프로그램이 종료됩니다.
MSalters

4

함수가 컴파일러가 소스를 "보지"않는 다른 함수를 호출하자마자 변수가 변경되었다고 가정해야합니다. 그렇지 않으면 아래에서 더 이상 문제가 발생할 수 있습니다. 예를 들어 "foo.cpp"에 다음이 있다고 가정합니다.

 void foo(int& x)
 {
    ifstream f("f.dat", ifstream::binary);
    f.read((char *)&x, sizeof(x));
 }

"bar.cpp"에 다음이 있습니다.

void bar(int& x)
{
  foo(x);
}

컴파일러 x는 변경되지 않는 (또는 더 적절하게 변경되고있는) 것을 어떻게 "알 수 bar있습니까?"

이것이 충분히 복잡하지 않다면 우리는 더 복잡한 것을 생각 해낼 수 있다고 확신합니다.


컴파일러는 bar x가 상수에 대한 참조에 의한 전달로 전달되면 x가 막대에서 변경되지 않는다는 것을 알 수 있습니다.
Cricketer

예,하지만 const_castin foo를 추가하면 여전히 x변경 될 것입니다. const변수 를 변경해서는 안된다는 계약을 위반할 것입니다. 하지만 무엇이든 "more const"로 변환 할 수 있고 const_cast존재하기 때문에 언어의 설계자들은 const가치가 변화 할 필요가 있다고 믿을만한 좋은 이유가 때때로 있다는 생각을 분명히 가지고있었습니다 .
Mats Petersson

@MatsPetersson : 나는 당신이 const_cast를한다면 컴파일러가 할 수 있기 때문에 깨지는 모든 조각들을 유지할 수 있다고 믿습니다. 그러나 그것을 보상 할 필요는 없습니다.
Zan Lynx

@ZanLynx : 네, 맞습니다. 그러나 동시에 캐스트가 존재합니다. 즉, 언어를 설계 한 사람이 "언젠가는이 기능이 필요할 수 있습니다."라는 아이디어를 가지고 있다는 의미입니다. 이는 전혀 유용한 작업을 수행하지 않는 것을 의미합니다.
Mats Petersson

1

일반적 으로 지적했듯이 컴파일러가 변수 변경 되는지 여부를 결정하는 것은 불가능 합니다.

CONST 다움을 검토 한 결과, 관심의 문제는 변수가 있다면 것으로 보인다 함수에 의해 변경 될 수있다. 포인터를 지원하는 언어에서는 이것조차 어렵습니다. 포인터로 다른 코드가 수행하는 작업을 제어 할 수 없으며 외부 소스에서 읽을 수도 있습니다. 메모리에 대한 액세스를 제한하는 언어에서는 이러한 유형의 보증이 가능할 수 있으며 C ++보다 더 적극적인 최적화를 허용합니다.


2
내가 바라는 한 가지는 언어에서 지원되는 것은 임시 참조, 반환 가능한 참조, 지속 가능한 참조 (또는 포인터)를 구분하는 것입니다. 임시 참조는 다른 임시 참조에만 복사 할 수 있고, 반환 가능한 참조는 임시 또는 반환 가능한 참조에 복사 할 수 있으며, 지속 가능한 참조는 어떤 방식 으로든 복사 할 수 있습니다. 함수의 반환 값은 "반환 가능한"매개 변수로 전달되는 가장 제한적인 인수에 의해 제한됩니다. 나는 많은 언어에서 참조를 전달할 때 그것이 얼마나 오래 사용될 수 있는지를 나타내는 것이 없다는 것이 불행하다고 생각합니다.
supercat

그것은 확실히 유용 할 것입니다. 물론 이에 대한 패턴이 있지만 C ++ (및 기타 여러 언어)에서는 항상 "속임수"가 가능합니다.
Krumelur

.NET이 Java보다 우월한 주요 방법은 임시 참조라는 개념이 있다는 것입니다.하지만 불행히도 객체가 속성을 임시 참조로 노출 할 수있는 방법은 없습니다 (제가보고 싶은 것은 속성을 사용하는 코드는 객체를 조작하는 데 사용되어야하는 코드 (임시 변수와 함께)에 대한 임시 참조를 전달합니다
supercat

1

질문을 더 구체적으로 만들기 위해 책의 저자가 염두에 두었을 수있는 다음과 같은 제약 조건을 제안합니다.

  1. 컴파일러가 변수의 불변성과 관련하여 특정 함수의 동작을 검사한다고 가정합니다. 정확성을 위해 컴파일러는 함수가 다른 함수를 호출하면 변수가 변경된 경우 (아래에 설명 된 별칭으로 인해) 가정해야합니다. 따라서 가정 # 1은 함수 호출을 수행하지 않는 코드 조각에만 적용됩니다.
  2. 변수가 비동기 또는 동시 활동에 의해 수정되지 않는다고 가정합니다.
  3. 컴파일러는 변수가 수정 될지 여부가 아니라 수정 가능한지 여부 만 결정한다고 가정합니다. 즉, 컴파일러는 정적 분석 만 수행합니다.
  4. 컴파일러가 올바르게 작동하는 코드 만 고려한다고 가정합니다 (배열 오버런 / 언더런, 잘못된 포인터 등은 고려하지 않음).

컴파일러 설계의 맥락에서 가정 1,3,4는 코드 생성 정확성 및 / 또는 코드 최적화의 맥락에서 컴파일러 작성자의 관점에서 완벽하게 합리적이라고 생각합니다. 가정 2는 volatile 키워드가 없으면 의미가 있습니다. 그리고 이러한 가정은 제안 된 답변을 훨씬 더 명확하게 판단 할 수있을만큼 질문에 초점을 맞 춥니 다. :-)

이러한 가정을 감안할 때 const-ness를 가정 할 수없는 주요 이유는 변수 앨리어싱 때문입니다. 컴파일러는 다른 변수가 const 변수를 가리키는 지 여부를 알 수 없습니다. 별칭은 동일한 컴파일 단위에있는 다른 함수로 인해 발생할 수 있습니다.이 경우 컴파일러는 함수를 살펴보고 호출 트리를 사용하여 별칭이 발생할 수 있는지 정적으로 결정할 수 있습니다. 그러나 별칭이 라이브러리 또는 기타 외부 코드로 인한 경우 컴파일러는 변수가 별칭인지 여부를 함수 입력시 알 수 없습니다.

변수 / 인수가 const로 표시되면 앨리어싱을 통해 변경해서는 안되지만 컴파일러 작성자에게는 매우 위험하다고 주장 할 수 있습니다. 인간 프로그래머가 변수를 실제로 알기 위해 전체 시스템이나 OS 또는 라이브러리의 동작을 알지 못하는 대규모 프로젝트의 일부로 변수 const를 선언하는 것은 위험 할 수 있습니다. ' t 변경.


0

변수가 선언되었다고 const해서 잘못 작성된 코드가이를 덮어 쓸 수 있다는 의미는 아닙니다.

//   g++ -o foo foo.cc

#include <iostream>
void const_func(const int&a, int* b)
{
   b[0] = 2;
   b[1] = 2;
}

int main() {
   int a = 1;
   int b = 3;

   std::cout << a << std::endl;
   const_func(a,&b);
   std::cout << a << std::endl;
}

산출:

1
2

이는 발생 a하고 b스택 변수이며, b[1]마찬가지로 동일한 메모리 위치로 일어난다 a.
Mark Lakata

1
-1. Undefined Behavior는 컴파일러의 동작에 대한 모든 제한을 제거합니다.
MSalters

반대표에 대해 확신이 없습니다. 이것은 const모든 것이 레이블이 지정 되어 있으면 컴파일러가 무언가가 진정으로 무엇인지 알아낼 수없는 이유에 대한 OP의 원래 질문에 대한 예제 일뿐 const입니다. 정의되지 않은 동작은 C / C ++의 일부이기 때문입니다. 나는 중단 문제 나 외부 사람의 의견보다는 그의 질문에 답할 수있는 다른 방법을 찾으려고 노력하고있었습니다.
Mark Lakata 2013-07-02

0

내 의견을 확장하기 위해 그 책의 텍스트는 문제를 모호하게 만드는 것이 명확하지 않습니다.

내가 언급했듯이, 그 책은 "모든 상상할 수있는 C ++ 함수를 작성하기 위해 무한한 수의 원숭이를 확보하자. 우리가 (원숭이가 작성한 특정 함수)) 변수를 선택하는 경우가있을 것이다. 함수가 해당 변수를 변경할지 여부를 확인할 수 없습니다. "

물론 주어진 응용 프로그램의 일부 (심지어 많은) 함수의 경우 이는 컴파일러에 의해 매우 쉽게 결정될 수 있습니다. 그러나 전부는 아닙니다 (또는 반드시 대부분).

이 함수는 쉽게 분석 할 수 있습니다.

static int global;

void foo()
{
}

"foo"는 분명히 "global"을 수정하지 않습니다. 그것은 아무것도 수정하지 않으며 컴파일러는 이것을 매우 쉽게 해결할 수 있습니다.

이 함수는 그렇게 분석 할 수 없습니다.

static int global;

int foo()
{
    if ((rand() % 100) > 50)
    {
        global = 1;
    }
    return 1;

"foo"의 작업은 런타임에 변경 될 수있는 값에 따라 달라 지므로 컴파일 타임에 "global"을 수정할지 여부를 결정할 수 없습니다 .

이 전체 개념은 컴퓨터 과학자가 생각하는 것보다 이해하기 훨씬 간단합니다. 함수가 런타임에 변경 될 수 있다는 점에 따라 다른 작업을 수행 할 수 있다면 실행될 때까지 수행 할 작업을 파악할 수 없으며 실행할 때마다 다른 작업을 수행 할 수 있습니다. 증명이 불가능하든 아니든, 분명히 불가능합니다.


당신이 말한 것은 사실이지만 컴파일 시간에 모든 것이 알려진 매우 간단한 프로그램의 경우에도 프로그램이 중지된다는 사실조차 증명할 수 없습니다. 이것이 중단 문제입니다. 예를 들어 Hailstone Sequences en.wikipedia.org/wiki/Collatz_conjecture를 기반으로 프로그램을 작성하고 하나로 수렴하면 true를 반환하도록 할 수 있습니다. 컴파일러는이를 수행 할 수 없으며 (많은 경우 오버플로가 발생하므로) 수학자조차 그것이 사실인지 여부를 알지 못합니다.
kriss

당신이 의미하는 경우 "가 어떤 당신은 아무것도 증명할 수있는 매우 간단한 찾고 프로그램"나는 전적으로 동의합니다. 그러나 Turing의 고전적인 Halting Problem 증명은 본질적으로 프로그램 자체가 모순을 설정하기 위해 중단 여부를 알 수있는 프로그램에 의존합니다. 이것은 구현이 아닌 수학이기 때문입니다. 확실히 컴파일 타임에 특정 변수가 수정 될 것인지, 프로그램이 중지 될 것인지 정적으로 결정할 수있는 프로그램이 있습니다. 수학적으로 증명할 수는 없지만 특정 경우에는 실질적으로 달성 할 수 있습니다.
El Zorko 2013
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.