2015-01-27 1 views
-4

반환 통근을 가정하고 나는 기능을 사용하는 경우컴파일러 제공 - 경고 C4013 : 'getche'undefined; 내 코드 개발을위한 비주얼 스튜디오를 사용하고 INT

컴파일러는 나에게이 경고를 준() getche

warning C4013: 'getche' undefined; assuming extern returning int 

하지만 getche() 함수는 예상대로 작동하며 컴파일러에서 이러한 경고를 표시하는 이유와이 경고를 어떻게 없앨 수 있습니까?

+2

'conio.h'가 포함됩니다. – Sadique

답변

3

컴파일러에서 알려주므로 getche이 정의되지 않았습니다. 이전에 정의되지 않은 기능의 사용을 허용하는 C 언어에 대한 규칙이 있습니다

int getche(void); 

:

일반적으로, 당신은 헤더 다소 유사 함수를 정의합니다 (예 : #include <conio.h>)를 포함 할 것 . 이 함수는 전달 된 정확한 인수 유형 (none, 따라서 void)을 취하고 int을 리턴한다고 가정합니다. 이 기능 (evil ™)과 실제로 링커 설정으로 인해 getche이 링크 된 사실로 인해 프로그램이 실제로 올바르게 작동합니다.

getche은 더 이상 사용되지 않으므로 대신 _getche을 사용해야합니다.

+0

감사합니다. 문제가 해결되었습니다. (창문에서 _getche(); – Sorcrer

1

내가 추가하고 싶은 한 가지 작은 점 : 이러한 오류를 수정하는 것은 선언이 누락되어 더 많은 오류가 발생할 수 있으므로 그리 중요하지 않습니다.

간단한 호출 foo(4)을 예로 들어보십시오. 이 호출이 작동하는 방법에 대한 추가 정보가 없다고 가정합니다. 그런 호출로부터 컴파일러는 무엇을 읽을 수 있습니까?

  1. 매개 변수의 수 (매우 분명합니다).
  2. 매개 변수의 유형 (4는 일반적으로 4 바이트 값으로 확장되고 64 비트 시스템에서는 4LL (8cc 값)까지 확장됩니다.
  3. 매개 변수가 스택에 푸시되어야하는 순서 (호출 규칙 - 대부분 C 규칙이지만 컴파일러 설정에 따라 다름).

그 전화에서 읽을 수없는 컴파일러는 무엇 :

  1. 값의 어떤 종류의 호출이 반환.

맞아요. foo은 다른 모듈이나 시스템 라이브러리에서도 정의 될 수 있습니다. 선언이없는 심볼 foo은 컴파일러가 완전히 알 수 없습니다. 그것은 단지 코드를 컴파일하기 때문에 심볼의 링키지에 대한 책임은 없습니다 (심볼에 변수 함수가 포함될 수 있기 때문에 심볼을 사용합니다).

이제 입니다. 컴파일러는 어떻게해야합니까?

  1. 각 호출에 대한 지침을 생성해야합니다. 호출 규칙에 따라 이러한 지침은 크게 다를 수 있습니다. 예를 들어 cdecl으로 호출자은 스택에서 인수를 푸시해야하며 각 함수를 호출하기 전에이 인수를 푸시해야합니다. stdcall으로 번으로은 스택을 정리해야합니다.

  2. 인수 유형이 무엇인지 알아야합니다. 글쎄요, 실제로 타입에 대해서는별로 신경 쓰지 않지만, 오브젝트가 차지하는 크기는 중요합니다. 20 바이트 구조체 객체는 스택에서 20 바이트를 필요로 하지요? 그리고 각 매개 변수를 입력해야합니다 (call-by-value).

  3. 그리고 함수의 반환 값에 대해 스택에 충분한 메모리를 예약해야합니다. 왜냐하면 : 함수가 반환하려고하는 것은 그 메모리에 저장됩니다. 함수가 20 바이트의 struct 객체를 반환하면 20 바이트가 필요합니다. 여태까지는 그런대로 잘됐다.

은 이제 아무것도 하지만 반환 값은 전화에서 읽을 수 있습니다 - 반환 값은 선언에 의해 제공해야합니다. 이 선언을 제공하지 않으면 컴파일러에서 반환 값의 스택에 sizeof(int) (대부분 4 바이트)을 예약하고 나머지는 링커에 남겨 둡니다.

링커는 foo(4 bytes) 기호를보고 foo(4 bytes)의 해당 정의를 찾습니다. 그리고 다른 모듈이나 시스템의 libc 또는 syscall 래퍼로 찾으면 링커는 내용을 담고 실행 파일을 생성합니다.

모두 괜찮습니까? 음, 아니에요.

예를 들어 memmem이라는 기능이 GNU 시스템에서 제공되며 을 정의 할 때 활성화되어 string.h을 포함하기 전에 활성화됩니다. 해당 함수를 포함하기 전에 _GNU_SOURCE을 정의하지 않으면 memmem의 선언을 건너 뛰고 컴파일러는 함수의 반환 값을 결정할 수 없으며 자동으로 4 바이트로 간주합니다. 32 비트 시스템에서 "OK"입니다. 그러나 프로그램이 64 비트 실행 파일로 컴파일되고 memmem에 전달되는 건초 더미가 0xFFFFFFFF을 가리키는 64 비트 포인터 인 경우 포인터의 상위 32 비트는 지워지고 있습니다 (예 : return (pointer&0xFFFFFFFFULL);). 그리고이 새로운 포인터는 "좋은 너바나"에 대응하여 "나쁜 너바나"라고 부르는 것을 가리킬 수 있습니다. "좋은 너바나"는 NULL이며,이 포인터가 참조 해제되지 않아야 함을 모든 사람이 볼 수 있습니다. "나쁜 너바나"를 가리키는 포인터에 대해 이렇게하는 것은 더욱 어렵습니다.

링커는 memmem 호출에 아무런 문제가 없습니다. 우리 시스템 라이브러리는 여전히 해당 기능을 알고 있기 때문입니다. 당신은 그것을 요구하지 않고 그것을 얻습니다. 그러나 그것을 사용하면 당신을 배신 할 것입니다.

따라서 컴파일러에 이 필요하지 않은 경우에도 선언이 필요하지만 여전히 제공하고 싶습니다.

관련 문제