source

함수는 반환문 없이 값을 반환합니다.

manycodes 2023. 9. 18. 22:34
반응형

함수는 반환문 없이 값을 반환합니다.

다음 코드의 출력이 올바른 이유는 무엇입니까?int GGT는 반품명세서가 없지만 코드는 어쨌든 작동합니까?전역 변수가 설정되어 있지 않습니다.

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

int GGT(int, int);

void main() {
    int x1, x2;
    printf("Bitte geben Sie zwei Zahlen ein: \n");
    scanf("%d", &x1);
    scanf("%d", &x2);
    printf("GGT ist: %d\n", GGT(x1, x2));
    system("Pause");
}

int GGT(int x1, int x2) {
    while(x1 != x2) {
        if(x1 > x2) {
            /*return*/ x1 = x1 - x2;
        }
        else {
            /*return*/ x2 = x2 - x1;
        }
    }
}

적어도 x86의 경우, 이 함수의 반환 값은eax등록하세요.거기에 있던 모든 것은 발신자가 반환 값으로 간주합니다.

왜냐면eax반환 레지스터로 사용되며, 보존할 필요가 없기 때문에 호출자에 의해 "보낸" 레지스터로 사용되는 경우가 많습니다.지역 변수 중 하나로 사용될 가능성이 매우 높다는 뜻입니다.마지막에 둘 다 같기 때문에 정확한 값이 남을 확률이 더 높습니다.eax.

이것이 작동하지 않아야 하며 모든 컴파일러와 대상 OS에서 작동하지 않아야 합니다.

아마도 int를 반환하는 함수는 항상 무언가를 반환하며, 그것은 보통 레지스터의 내용입니다.반환 값에 사용되는 레지스터가 함수에서 반환되기 전 마지막 식을 계산하는 데 사용되는 것과 동일한 경우가 발생할 수 있습니다(확실히 x86 대상에서).

즉, 반환이 없음을 감지하는 최적화 컴파일러는 이 함수의 코드를 완전히 제거할 수 있습니다.이후 더 높은 최적화 수준을 활성화할 때 보이는 효과가 사라질 수 있습니다.

gcc로 테스트했습니다.

최적화하지 않은 gcc: 입력 10, 20 -> 결과는 10

gcc -O1 입력 10, 20 -> 결과 1

gcc -O2 입력 10, 20 -> 결과 0

함수가 값을 반환하도록 정의되었지만 반환하지 않고 호출 함수가 반환 값을 사용하려고 하면 정의되지 않은 동작을 호출합니다.

이는 C 표준의 섹션 6.9.1p12에 명시되어 있습니다.

만약에}함수를 종료하고 함수 호출의 값이 호출자에 의해 사용되는 경우, 동작은 정의되지 않습니다.

이 경우 프로그램이 제대로 작동한 것처럼 보이는 '행운'을 얻었지만, 그에 대한 보장은 없습니다.다른 최적화 설정이나 다른 컴파일러로 컴파일했다면 결과가 달라질 수 있습니다.

따라서 이 이야기의 교훈은 함수가 값을 반환한다고 하면 항상 값을 반환해야 한다는 것입니다.

x86에서 반환 값은 EAX 레지스터에 저장되며, 이 레지스터는 산술 연산(또는 적어도 뺄셈)의 결과를 저장하는 데에도 "우연히" 사용됩니다.컴파일러에서 생성된 어셈블리를 보고 이를 확인할 수 있습니다.kris에 동의합니다. 항상 그러할 것이라고 가정할 수는 없으므로 반환 값을 명시적으로 지정하는 것이 좋습니다.

공식 언어:

기능 6.9.1
...
12 만약에 }함수를 종료하고 함수 호출의 값이 호출자에 의해 사용되는 경우, 동작은 정의되지 않습니다.

여기서 "정의되지 않은 행동"은 다음을 의미합니다.

1단정할 수 없는 행동
휴대가 불가능하거나 잘못된 데이터의 프로그램 구성자를 사용할 때, 본 국제 표준이 요구 사항을 부과하지 않는 거동

할 수 무시하는 것, 하는 것(되지 않는 것), 2고는로을히는터역는램행에의행을는로된할수s2행mee로된drn는을2eg,e의n고gesog,에hrnc할rtyhnese수는n동하는 것(진단 메시지의 발행 여부에 관계없이)까지 가능한 미정의 행동,(진단 메시지 발행과 함께) 번역 또는 실행을 종료합니다.

3 예 정의되지 않은 동작의 예로는 정수 오버플로에 대한 동작이 있습니다.

C 2011 온라인 드래프트

믿기 힘들겠지만, 함수는 다음과 같은 것을 입력했습니다.void를 가질 필요는 없습니다.return진술.언어 문법에 의해 강제되는 것이 아니며, 비언어적인 것에 대한 제약도 없습니다.void을야다는다가 포함되어야 .return진술. 유일 제약 만약 그것 존재한다면 조건 , a, a가 한 제약 입니다.returna술로 의void는 어떤, a는떤의을지다다지nat는을 . 그리고 areturn이 아닌 진술.void함수는 식의 값을 반환해야 합니다.

왜 그런거죠?

에는 C Δ a Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δ Δvoid데이터 유형, 그리고 해당 부작용에 대해서만 실행되고 값을 반환하지 않는 서브루틴을 지정할 방법이 없었습니다."아무것도를 돌려줄 에, 도도,return문이 필요 없습니다.도 " C한에적 다 이 적 다 를 가지고 .int" 선언 - 형식 없이 함수 본문을 정의할 수 있으며 컴파일러는 이를 입력했다고 가정합니다.int:

foo( a, b )   // old style parameter declarations
  int a;      // still legal, but no longer really used
  char *b;    // for very good reasons
{
  // do something interesting with a and b
}

foo록로됩니다를 하도록 암묵적으로 됩니다.int, 값이 명시적으로 반환되지 않는 경우에도.발신자가 사용을 시도하지 않는 한 이것은 괜찮습니다. foo존재하지 않는 반환 값입니다.따라서 "절차"(부작용만을 위해 실행되는 기능)가 명시적으로 입력되지 않고, 그렇지 않은 일종의 컨벤션이 발달했습니다.return진술.

레거시 코드는 영원하기 때문에, 행동은return는) 인 C는이지다근thn,etds의sn근cfeecnt'는n이 비록 암묵적이긴 하지만int선언은 C99에서 삭제되었습니다.

이러한 경우 GCC는 "ret" 명령을 붙여넣는 반면 clang은 "ud2"를 붙여넣고 런타임에 앱이 충돌합니다.

언급URL : https://stackoverflow.com/questions/4644860/function-returns-value-without-return-statement

반응형