2016-09-14 5 views
0

KR C 책을 읽고 있는데 이해할 수없는 함수 정의가 있습니다. 87 페이지의 qsort() 기능입니다. 그것은 qsort() 기능 내부 swap() 함수를 선언 :C 함수 내에서 함수 선언하기

함수 외부 swap() 기능을
void qsort(args) 
{ 
... 
void swap(arguments); 
... 
swap(a,b); 
} 

void swap(arguments){ 
... 
} 

를 선언 할 수 없습니다해야합니까? 왜 내부에 신고합니까 qsort()?

+3

선언되지 않은 함수는 사용할 수 없습니다. 사용하기 전에 선언하고 선언이 범위 내에있는 한 선언하는 곳은 특히 중요하지 않습니다. – Tibrogargan

+0

범위가 정의 된 블록 내부로 제한되지 않습니까? 이 경우'swap()'은'qsort()'함수 내에서만 유효하다. – Arash

+0

@Arash Yes. 그리고 정의 된 파일의 일부분에서도 마찬가지입니다. deinition은 선언이기 때문에. – hyde

답변

7

당신은 K & R C 프로그래밍 언어와 아마도 ANSI C가있는 제 2 판을 읽고 있다고 생각합니까? https://hassanolity.files.wordpress.com/2013/11/the_c_programming_language_2.pdf에 PDF가 있고 87 페이지에는 빠른 정렬 알고리즘을 사용한 재귀에 대한 설명이 나와 있습니다.

다양한 C 표준 https://en.wikipedia.org/wiki/ANSI_C을 비교하고 대조이 위키 백과의 항목을 참조하십시오

두 번째 에디션 저작권이 좋은 소재의 1988 년 많은 그대로 K & RC 책은 이전 스타일 C하지만이 관점에서 읽을 필요 더 오래된 스타일이고 C 표준은 ANSI C 이후로 변경되었습니다. 가장 중요한 것은 컴파일러가 오류 및 경고로 선언해야하는 것에 대한 더 나은 사양입니다. 현대 C 표준에서 더 이상 수용 할 수없는 것들이 ANSI C에서 완벽하게 받아 들여졌습니다. C 프로그래밍 언어 사양을 강화하고 몇 가지 추가 키워드와 구문을 제공함으로써 컴파일러가 더 나은 정적 검사를 제공하기 위해 많은 노력을 기울였습니다.

swap()에 대한 전방 선언이 있거나 함수가 실제로 사용되기 전에 소스 코드가있는 함수 정의가 있어야합니다. 이를 통해 C 컴파일러는 가능한 사용 오류를 검사하기 위해 선언 또는 정의에 대해 함수의 사용을 검사 할 수 있습니다.

그러나 C 프로그래밍 언어를 사용하면 함수를 정의하거나 선언하기 전에 함수를 사용하면 일반적으로 Visual Studio 2013 warning C4013: 'swap' undefined; assuming extern returning int의 경고와 같은 경고가 표시됩니다.

clanggcc의 최신 버전과 Visual Studio 2015가 C11을 구현하기 시작했습니다. 일부 컴파일러는 경고를 개선하고/또는 일부 경고를 오류로 바꾸기위한 추가 옵션을 제공합니다.

예를 들어, testit.c 파일 (C 소스 코드의 .c 파일 확장명을 확인하십시오.)에 다음 소스 코드가 있고 경고 수준 4를 사용하여 Visual Studio 2013을 사용하여 컴파일하면 일련의 경고는 있지만 오류는 없습니다. Visual Studio는 동일한 구문의 경우에도 C++의 표준 및 규칙보다 느슨한 표준 및 규칙을 사용하여이를 C 소스로 컴파일합니다.

이 소스의 두 가지 다른 버전을 컴파일했습니다. 두 번째 버전에서 앞쪽 선언이 주석 처리되고 주석 처리가 해제 된 버전이 하나 있습니다. Visual Studio의 C 컴파일러가 전달 선언없이 함수를 사용할 수 있다는 경고 메시지가 표시됩니다.

두 번째 실행에서 2 행의 전방 선언에 주석 처리가 해제 된 경우 함수 범위 내에서 함수에 대한 전방 선언 (예 : warning C4210: nonstandard extension used : function given file scope)에 대한 경고가 표시됩니다.

두 번째 실행에서 사용할 수있는 전달 선언을 사용하면 컴파일러에서 가능한 사용 오류를 식별하고 경고를 내고 한 경우 실제 오류가 발생할 수 있습니다.

인수의 수는 첫 번째와 두 번째 컴파일에서 모두 다르지만 두 번째 컴파일에서는 앞뒤 선언이 주석 처리되지 않고 컴파일러에서 사용할 수 있다는 점에 유의하십시오. 추가 인수에 대한 경고가 표시됩니다.

int func1() {      // line 1 
// int swap(int a, int b);   // line 2, forward declaration for function swap 

    int j = swap(1, 2); 

    return 0; 
} 

int func2() {       // line 9 
    struct { 
     int a; 
     int b; 
     int c; 
    } mm = { 0 }; 

    int k = swap(4, 5, 8);    // line 16 

    float ff = swap(4.0, 5.0, 8.0); // line 18 

    int k2 = swap(mm, 2, 3);   // line 20 

    return 1; 
} 

int swap(int a, int b) {    // line 25 
    return a + b; 
} 

경고는 다음과 같습니다

1>------ Build started: Project: ConsoleApplication3, Configuration: Debug Win32 ------ 
1> testit.c 
1>c:\users\projects\consoleapplication3\testit.c(2): warning C4210: nonstandard extension used : function given file scope 
1>c:\users\projects\consoleapplication3\testit.c(4): warning C4189: 'j' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit.c(16): warning C4020: 'swap' : too many actual parameters 
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4244: 'function' : conversion from 'double' to 'int', possible loss of data 
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4020: 'swap' : too many actual parameters 
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4244: 'initializing' : conversion from 'int' to 'float', possible loss of data 
1>c:\users\projects\consoleapplication3\testit.c(20): error C2440: 'function' : cannot convert from '' to 'int' 
1>c:\users\projects\consoleapplication3\testit.c(20): warning C4024: 'swap' : different types for formal and actual parameter 1 
1>c:\users\projects\consoleapplication3\testit.c(20): warning C4020: 'swap' : too many actual parameters 

지금 :

1>------ Build started: Project: ConsoleApplication3, Configuration: Debug Win32 ------ 
1> testit.c 
1>c:\users\projects\consoleapplication3\testit.c(4): warning C4013: 'swap' undefined; assuming extern returning int 
1>c:\users\projects\consoleapplication3\testit.c(4): warning C4189: 'j' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4244: 'initializing' : conversion from 'int' to 'float', possible loss of data 
1>c:\users\projects\consoleapplication3\testit.c(16): warning C4189: 'k' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit.c(20): warning C4189: 'k2' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4189: 'ff' : local variable is initialized but not referenced 
1> ConsoleApplication3.vcxproj -> C:\Users\Projects\Debug\ConsoleApplication3.exe 

난 후 주석 내가 오류와 함께 경고의 다음과 같은 컴파일러 출력을 볼 수있는 기능 swap()에 대한 전방 선언하는 경우 C++ 프로그래밍 언어는 다르며 이러한 종류의 느슨 함을 허용하지 않습니다. 그래서 C++이 C와 함께 역사를 공유하지만 C++은 다른 언어이지만 관련성이 있습니다.

동일한 소스를 testit2.cpp 파일에 복사 한 다음 컴파일하면 다른 오류가 표시됩니다.

우선 선언문은 swap()입니다.

1> testit2.cpp 
1>c:\users\projects\consoleapplication3\testit2.cpp(4): error C3861: 'swap': identifier not found 
1>c:\users\projects\consoleapplication3\testit2.cpp(16): error C3861: 'swap': identifier not found 
1>c:\users\projects\consoleapplication3\testit2.cpp(18): error C3861: 'swap': identifier not found 
1>c:\users\projects\consoleapplication3\testit2.cpp(20): error C3861: 'swap': identifier not found 

그리고 앞으로 선언문의 주석을 제거하십시오.

1> testit2.cpp 
1>c:\users\projects\consoleapplication3\testit2.cpp(4): warning C4189: 'j' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit2.cpp(16): error C3861: 'swap': identifier not found 
1>c:\users\projects\consoleapplication3\testit2.cpp(18): error C3861: 'swap': identifier not found 
1>c:\users\projects\consoleapplication3\testit2.cpp(20): error C3861: 'swap': identifier not found 

그리고 지금 있도록 내가 파일 범위에 기능 func1()의 범위에서 swap()의 전방 선언을 이동하면 마지막 라인 1 그럼 내가 볼 수 있습니다 다음, 다른 오류 :

1> testit2.cpp 
1>c:\users\projects\consoleapplication3\testit2.cpp(4): warning C4189: 'j' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit2.cpp(16): error C2660: 'swap' : function does not take 3 arguments 
1>c:\users\projects\consoleapplication3\testit2.cpp(18): error C2660: 'swap' : function does not take 3 arguments 
1>c:\users\projects\consoleapplication3\testit2.cpp(20): error C2660: 'swap' : function does not take 3 arguments 
+1

K & R 제 2 판은 C90을 의미하는 "ANSI C"를 간신히 따릅니다. 즉, Visual Studio를 사용하여 최신 C 표준 준수를 증명하는 것이 최선의 방법은 아니라고합니다. 프로토 타입없이 VS에서 함수를 사용할 수있는 이유는 VS C 컴파일러가 구식이며 비 호환 쓰레기이기 때문입니다. 현대 C 프로그래밍을 원할 경우 K & R 책과 Visual Studio를 모두 지우십시오. – Lundin