programing

C의 동일한 디렉토리에 있는 다른 파일에서 함수 호출

lovejava 2023. 11. 5. 10:48

C의 동일한 디렉토리에 있는 다른 파일에서 함수 호출

저는 C를 배우고 있지만 자바와 같은 상위 프로그래밍 언어에 대한 오랜 경험이 있습니다.

헤더 파일에 대해 읽고 있어서 가지고 놀고 있었는데 #포함 없이 다른 파일에서 함수를 호출할 수 있다는 것을 알게 되었습니다(같은 디렉토리에 있음). 어떻게 가능합니까?!그런 식으로 구성된 것은 make file, linker입니까? 아니면 무엇입니까?

두개의 파일이 있습니다.

main.c
add.c

main.c는 함수를 호출합니다.add(int x,int y)add.c에서 왔는데, #include add.c 전에 실수로 #include add.c 전에 컴파일을 잘못해서 작동했어요! 더 헷갈리는 것은 i#include add.c를 include할 때 함수 add에서 다중 정의 오류가 발생한다는 것입니다.

여기에는 몇 가지 다른 일들이 벌어지고 있습니다.먼저 여러 파일의 기본적인 컴파일이 어떻게 작동하는지에 대해 알아보겠습니다.

파일이 여러 개인 경우, 중요한 것은 함수의 선언과 정의의 차이입니다.이 정의는 아마도 함수를 정의할 때 익숙한 것일 것입니다.당신은 그 기능의 내용을 적습니다, 예를 들면,

int square(int i) {
    return i*i;
}

그러나 이 선언을 통해 컴파일러에게 함수가 존재한다는 것을 알면서도 컴파일러에게 함수가 무엇인지 알려주지 않는다는 것을 선언을 통해 함수가 존재한다는 것을 선언할 수 있습니다.예를 들어, 당신은 글을 쓸 수 있습니다.

int square(int i);

컴파일러는 함수 "제곱"이 다른 곳에서 정의되는 것을 예상할 것입니다.

이제 상호 운용할 두 개의 다른 파일이 있다면(예를 들어 함수 "square"가 add.c에 정의되어 있고 main.c에서 square(10)를 호출하려고 한다고 가정하자) 정의와 선언을 모두 수행해야 합니다.먼저 add.c에서 제곱을 정의합니다.그러면 메인 시작에 신고를 하게 됩니다.컴파일러가 main.c를 컴파일할 때 다른 곳에 정의된 함수 "square"가 있다는 것을 알게 해줍니다.이제 main.c와 add.c 둘 다 개체 파일로 컴파일해야 합니다.전화해서 할 수 있습니다.

gcc -c main.c
gcc -c add.c

이렇게 하면 main.o 파일과 add.o 파일이 생성됩니다.컴파일된 함수가 포함되어 있지만 실행이 가능하지는 않습니다.여기서 이해해야 할 중요한 점은 main.o가 어떤 의미에서 "불완전"하다는 것입니다.main.o를 컴파일할 때 함수 "square"가 존재하지만 함수 "square"는 main.o 내부에 정의되지 않는다고 말했습니다.따라서 main.o는 함수 "square"에 대해 일종의 "dangling reference"를 갖습니다."square" 정의를 포함하는 다른 .o(또는 .so 또는 .a) 파일과 결합하지 않는 한 전체 프로그램으로 컴파일되지 않습니다.만약 당신이 main.o를 프로그램에 연결하려고 한다면, 즉.

gcc -o executable main.o

컴파일러가 함수 "square"에 대한 dangling reference를 해결하려고 하지만 이에 대한 정의를 찾지 못하므로 오류가 발생할 것입니다.그러나 링크할 때 add.o를 포함하면 (링크는 .o 파일을 실행 파일 또는 .so 파일로 변환하는 동안 정의되지 않은 함수에 대한 이러한 모든 참조를 해결하는 프로세스입니다) 문제가 발생하지 않습니다.

gcc -o executable main.o add.o

이것이 C 파일 전체에서 기능적으로 기능을 사용하는 방법입니다. 하지만 스타일적으로 방금 보여드린 것은 "올바른 방법이 아닙니다.제가 한 유일한 이유는 "#include magic"에 의존하는 것보다 상황을 이해하는 데 더 도움이 될 것이기 때문입니다.메인.c 상단에서 사용하려는 모든 기능을 다시 선언해야 한다면 작업이 조금 복잡해진다는 것을 이전에 알아차렸을 수도 있습니다. 이것이 C 프로그램이 확장자가 .h인 "헤더"라고 불리는 도우미 파일을 자주 사용하는 이유입니다.헤더의 개념은 정의 없이 함수들의 선언만을 포함한다는 것입니다.이런 식으로 add.c에 정의된 함수를 사용하여 프로그램을 컴파일하려면 사용 중인 모든 함수를 수동으로 선언할 필요가 없으며 코드에 전체 add.c 파일을 #포함할 필요도 없습니다.대신 단순히 add.c의 모든 함수의 선언을 포함하는 add.h를 #포함할 수 있습니다.

#의 새로 고침 프로그램은 다음을 포함합니다. #include는 한 파일의 내용을 다른 파일에 직접 복사하기만 하면 됩니다.예를 들어, 코드는

abc
#include "wtf.txt"
def

와 정확히 동치입니다.

abc
hello world
def

그것을 전제로.txt에는 "hello world"라는 텍스트가 포함되어 있습니다.

따라서 add.c의 모든 선언을 add.h(즉, add.h)에 넣으면 됩니다.

int square(int i);

그리고 메인.c의 맨 위에 우리는 글을 씁니다.

#include "add.h"

이는 기능적으로 메인.c 상단의 함수 "square"를 수동으로 선언한 것과 동일합니다.

따라서 헤더를 사용하는 일반적인 생각은 #포함하기만 하면 필요한 모든 기능을 자동으로 선언하는 특수 파일을 가질 수 있다는 것입니다.

그러나 헤더에는 일반적인 용도도 한 가지 더 있습니다.main.c가 50개의 다른 파일의 함수를 사용한다고 가정해 보겠습니다.main.c 상단은 다음과 같습니다.

#include "add.h"
#include "divide.h"
#include "multiply.h"
#include "eat-pie.h"
...

대신, 사람들은 종종 #포함된 모든 것들을 메인으로 옮깁니다.h 헤더 파일과 main.c에서 # include main.h.이 경우 헤더 파일은 두 가지 용도로 사용됩니다.다른 파일에 포함되어 있을 때 main.c에서 사용할 있도록 함수를 선언하고 main.c에서 포함되어 있을 때 main.c의 모든 종속성을 포함합니다.이런 식으로 사용하면 종속성의 사슬도 가능합니다.#include add.h를 포함하면 add.c에 정의된 함수를 얻을 수 있을 뿐만 아니라 add.cuses가 사용하는 함수도 암묵적으로 얻을 수 있습니다.

또한, 더 미묘하게도, 자체 .c 파일의 헤더 파일을 포함한 #는 사용자가 저지르는 오류를 암묵적으로 확인합니다.예를 들어 제곱을 실수로 정의한 경우

double square(int i);

add.h, main.o를 링크할 때까지 보통 인식하지 못할 수도 있습니다.o는 제곱의 정의를 찾고 add.o는 호환되지 않는 또 다른 정의를 제공합니다.그러면 링크할 때 오류가 발생하므로 나중에 빌드 과정에서 오류를 인식할 수 있습니다.그러나, 만약 당신이 add.c의 add.h를 컴파일러에 #포함한다면, 당신의 파일은 다음과 같이 보입니다.

#include "add.h"
int square(int i) {
    return i*i;
}

# include 문장을 처리한 후에 다음과 같이 보일 것입니다.

double square(int i);
int square(int i) {
    return i*i;
}

컴파일러가 add.c를 컴파일할 때 알아채고 알려줄 것입니다.이러한 방식으로 자신의 헤더를 포함하면 제공하는 기능의 유형을 다른 파일에 허위로 광고하는 것을 방지할 수 있습니다.

함수를 선언하지 않고 사용할 수 있는 이유

당신이 알아차린 것처럼, 어떤 경우에 당신은 함수를 모든 것을 선언하거나 그것을 선언하는 파일을 포함하지 않고 실제로 함수를 사용할 수 있습니다.이건 바보같은 짓이고 모두가 바보같은 짓이라는 데 동의합니다.그러나 C 프로그래밍 언어(및 C 컴파일러)의 레거시 기능으로 함수를 먼저 선언하지 않고 사용하면 함수 반환 형식 "int"로 가정합니다.따라서 실제로 함수를 사용하는 것은 함수가 아직 선언되지 않은 경우 "int"를 반환하는 함수로서 함수를 암묵적으로 선언하는 것입니다.생각해보면 아주 이상한 행동이고, 그런 행동을 한다면 컴파일러가 경고를 해줘야 합니다.

헤더 가드

또 하나의 일반적인 관행은 "헤더 가드"를 사용하는 것입니다.헤더 가드를 설명하기 위해 가능한 문제를 살펴보겠습니다.우리가 herp.c와 derp.c라는 두 개의 파일을 가지고 있고, 둘 서로에 포함된 기능을 사용하고 싶어한다고 가정해 보겠습니다.위의 지침에 따라, 당신은 그 선에 헤르페스가 있을 수 있습니다.

#include "derp.h"

선과 함께 더피시(derp.h).

#include "herp.h"

자, 생각해보면 #"derp"를 포함합니다.h"는 derp.h의 내용으로 변환되며, 여기에는 행 # include "herp.h"가 포함되며, 이는 herp.h의 내용으로 변환되며, 는 다음을 포함합니다.그래서 컴파일러는 영원히 포함된 것들을 확장할 것입니다.마찬가지로 main.h #가 herp.h와 derp.h를 모두 포함하고 herp.h와 derp.h가 모두 add.h를 포함하면 main.h에서 add.h의 복사본이 두 가 되고, 하나는 herp.h를 포함한 결과이고, 하나는 derp.h를 포함한 결과입니다.그래서 해결책은?"헤더 가드", 즉 헤더가 두 번 포함되는 것을 방지하는 코드 조각입니다.예를 들어 add.h의 경우 일반적인 방법은 다음과 같습니다.

#ifndef ADD_H
#define ADD_H

int sqrt(int i);
...
#endif

이 코드 조각은 기본적으로 "ADD_H"가 이미 정의되어 있는지 확인하기 위해 전처리기(모든 "#XXX" 문을 처리하는 컴파일러 부분)에 지시하는 것입니다.그렇지 않은 경우(ifndef), 먼저 "ADD_H"를 정의합니다(이러한 맥락에서 ADD_H는 정의되지 않아도 되고 정의되지 않은 부울일 뿐입니다). 그리고 헤더의 나머지 내용의 나머지 부분을 정의합니다.그러나 ADD_H가 이미 정의되어 있는 경우 #ifndef 블록 외부에 아무것도 없기 때문에 이 파일을 포함한 #는 아무런 작업도 수행하지 않습니다.따라서 주어진 파일에 처음 포함될 때만 해당 파일에 텍스트를 추가할 수 있습니다.그런 다음 #including(포함)은 파일에 추가 텍스트를 추가하지 않습니다.ADD_H는 add.h가 아직 포함되었는지 여부를 추적하기 위해 선택한 임의 기호일 뿐입니다.모든 헤더에 대해 다른 기호를 사용하여 아직 포함되었는지 여부를 추적합니다.예를 들어, herp.h는 ADD_H 대신 HERP_H를 사용할 것입니다."헤더 가드"를 사용하면 위에 나열한 문제를 해결할 수 있습니다. 파일의 복사본이 중복되거나 #include의 무한 루프가 있습니다.

문제는 당신이 그 일에 관여해서는 안 된다는 것입니다.#include파일을 입력합니다.

다른 파일에서 함수를 사용하려면 함수를 선언해야 합니다.일반적으로 모든 .c 파일(main.c 제외)에는 .c 파일에 정의된 모든 기능을 적절히 선언하는 관련 헤더(.h) 파일이 있습니다.원하는 만큼 선언할 수 있지만(모든 선언이 동일한 한), 한 가지 정의만 있을 수 있습니다.

네가 네게 무슨 일이 생기니?#include "add.c"add.c의 텍스트가 main.c에 포함되어 main.c의 정의(그리고 부작용으로 선언)를 제공한다는 것입니다.add. 그런 다음 add.c를 자체적으로 컴파일하면 다른 정의가 생성됩니다.add. 따라서 함수에 대한 정의는 두 가지가 있는데 컴파일러는 어떤 것을 사용해야 할지 몰라서 기겁을 합니다.

로 변경하시면#include "add.h", 여기서 add.h는 다음과 같습니다.

#ifndef ADD_H
#define ADD_H

extern int add(int x, int y);

#endif /* ADD_H - Google "include guard" for more info about this trickery */

그럼 main.c는 다음과 같은 선언을 합니다.add함수를 사용할 수 있지만 정의는add는 add.c 파일에만 상당히 확실하게 있으므로 한 번만 존재하므로 제대로 컴파일됩니다.

여기 다른 c 프로그램에서 함수를 호출하는 간단한 예가 있습니다.

메인 프로그램을 main.c로 하고 function.c를 function.c로 잡고 있는 프로그램을 function.h라고 하는 헤더 파일을 만들고 있습니다.

본전의

#include"function.h"
int main()
{
     int a = sum(1,2);
     return a;
}

함수.c

int function(int a,int b)
{
    return a+b;
}

함수.h

int function(int,int);

컴파일하려면 아래에 주어진 명령을 사용합니다.

g++ main.c function.c -o main

자세한 설명은 여기 있습니다.메인 프로그램에서 나는 2개의 숫자를 합하도록 함수를 불렀습니다.메인 프로그램의 값 1과 2는 액세스 포인트 또는 브리지를 함수에 고정하는 헤더 function.h를 통해 function.c의 함수에 피드되었습니다.

자세한 내용은 아래 링크를 확인할 수 있습니다.

http://www.cplusplus.com/forum/beginner/34691/

https://social.msdn.microsoft.com/Forums/en-US/4ea70f43-a0d5-43f8-8e24-78e90f208110/calling-a-function-in-a-file-from-another-file?forum=winembplatdev

결과를 확인하기 위해 인쇄문을 추가하거나 파일 메인 실행 후 echo $?를 사용합니다.

C에서 전화를 할 때는 신고가 필요 없기 때문에 전화를 할 수 있습니다.그러나 반환 유형을 알 수 없으므로 기본값은 다음과 같습니다.int. 이것은 부분적으로 C의 기본 호출 규약과 적어도 다음과 같은 유형의 기본 승격 때문에 가능합니다.int정확.

호출하는 함수를 정의하는 헤더를 포함하면 컴파일러는 함수에 대한 호출이 인수의 정확한 개수와 유형을 갖는지 확인할 수 있습니다.

함수 정의를 포함하는 경우 다음과 같이 저장소를 지정하지 않으면 내보냅니다.static. 당신도 편집하고 링크하고 있으니까요.add.c, 그 이후로 둘 중 하나나 둘 다 내보내지 않고는 이것을 추가할 수 없습니다.add.

단순히 모든 기능을 포함시키려면 헤더에 정의를 담고 스토리지 지정자를 표시하는 것이 좋습니다.

언급URL : https://stackoverflow.com/questions/6618921/calling-a-function-from-another-file-in-the-same-directory-in-c