함수는 반환문 없이 값을 반환합니다.
다음 코드의 출력이 올바른 이유는 무엇입니까?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 예 정의되지 않은 동작의 예로는 정수 오버플로에 대한 동작이 있습니다.
믿기 힘들겠지만, 함수는 다음과 같은 것을 입력했습니다.void
를 가질 필요는 없습니다.return
진술.언어 문법에 의해 강제되는 것이 아니며, 비언어적인 것에 대한 제약도 없습니다.void
을야다는다가 포함되어야 .return
진술. 유일한 제약 만약 그것이 존재한다면 조건은 , a, a가 한 제약 입니다.return
a술로 의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
'source' 카테고리의 다른 글
SQL 개발자에서 tnsnames.ora를 찾을 수 있는 위치? (0) | 2023.09.18 |
---|---|
하이픈을 낙타 케이스로 변환(camelCase) (0) | 2023.09.18 |
MySQL 테이블에서 두 번째로 높은 값 가져오기 (0) | 2023.09.18 |
Java Apache POI 라이브러리를 사용하여 XLSX 파일에서 특정 셀의 값을 가져오는 방법 (0) | 2023.09.18 |
Google 차트 창 크기 조정/축소 (0) | 2023.09.18 |