헤더파일 관련

asleea의 이미지

#include 에서 .h 파일 하고 .c 파일이 둘 다 되는데

헤더파일 하고 일반 c 파일하고 차이점이 먼가요 .?

익명 사용자의 이미지

간단합니다.

void func();

void func() { printf("This is a function."); }

이 둘의 차이입니다.

asleea의 이미지

헤더파일이 아니더라도 그냥 일반 시 파일에 넣어서 include 해줘도 작동을 하는데

왜 헤더파일을 쓰는지 궁굼합니다.

hys8287의 이미지

h는 선언 c(pp)는 정의를 하도록 되어있는데

만약 프로그램이 커져서
하나의 함수, 변수를 다른 여러개의 파일에서 쓸 수 있을텐데

만약 둘을 분류하지 않고
h에만 정의까지 해둔다면

다중정의가 되서 에러를 뿜습니다.

chadr의 이미지

선언은 헤더
구현은 소스

이것을 꼭 지켜주시면 꼬일일이 없습니다. 그리고 그렇게 하라고 구분해 놓은것이 저것들입니다.

따라서 헤더에서 소스를 include한다든가 하는 것은 매우 안좋은 설계입니다.
가끔 소스에서 다시 소스를 include하는 설계도 있는데 이것도 매우 안좋은 설계입니다.

-------------------------------------------------------------------------------
It's better to appear stupid and ask question than to be silent and remain stupid.

tachyon92의 이미지

#include는 지정된 파일을 단순 삽입하라는 지시어입니다. 헤더파일과 소스파일은 사실은 단순한 텍스트파일이고, 단지 c 문법에 맞게 선언과 구현, 또는 선언만으로 구성되어 있을 뿐이죠.


"a.h"와 "a.c"가 다음과 같을 때,

"a.h"

void hello();

"a.c"
#include "a.h"
 
void hello()
{
	printf("Hello World.\n");
}


"a.c"를 컴파일하면, 컴파일러가 파싱하는 구문은 실제로는 다음과 같습니다.

void hello();
 
void hello()
{
	printf("Hello World.\n");
}


"b.c"가 있어서

#include "a.h"
 
int main(void)
{
	hello();
}

컴파일하면 파싱되는 구문은

void hello();
 
int main(void)
{
	hello();
}

이므로 main() 함수에서 hello() 함수를 호출하기 전에 hello() 함수가 선언됨으로써 hello() 함수의 이름과 형, 그리고 함수의 존재 여부를 알 수 있습니다. (물론, 실재로는 존재하지 않거나 형이 다를 수도 있습니다.)
따라서, 이후에 hello() 함수를 쓸 수 있게 되는 거죠.

"a.h"의 파일 이름을 "asdf.c"로 바꾼 다음, 모든 #include "a.h" 를 #include "asdf.c"로 바꾸면 정확하게 똑같이 컴파일 됩니다. 심지어 "asdf"나 "asdf.exe" 등 어떤 이름도 상관 없습니다.

파일 확장자가 파일의 종류를 결정짓는 것이 아니라, 파일 내용으로부터 이미 결경된 파일의 종류에 따라 파일 이름에 접미사를 붙여 구분지어 놓은 것에 불과하기 때문입니다.

tachyon92의 이미지

덧붙이자면,
"a.c" 컴파일한 결과가 "a.obj", "b.c" 컴파일한 결과가 "b.obj"라면

"a.obj" 안에는 _hello 라는 이름의 컴파일된 (기계어로 된) 함수와
"b.obj" 안에 _main 라는 이름의 컴파일된 함수가 생기게 됩니다.
(사실 함수인지 변수인지조차 모르고 이름만 남아있을 뿐입니다.)

둘을 linker가 "b.obj"에서 _main 이라는 함수를 찾아 프로그램의 시작점으로 삼고, _main 에서 참조한 _hello 함수를 "a.obj"에서 찾아 실제 주소로 바꾸어 줍니다.


만약, "c.c"라는 소스파일이 추가되었고 "a.h" 를 include한다고 한다면, 문제가 없습니다.

"b.c", "c.c"에서 "a.h" 대신 "a.c"를 include한다면, 역시 컴파일에는 문제가 없습니다.
하지만 "a.obj"에도 _hello가 생기고, "c.obj"에도 _hello가 생기게 됩니다.

문제는 linker가 _hello 함수를 찾을 때 같은 이름의 _hello가 두 개가 존재하므로 에러를 뿜어냅니다.


반대로 "a.c"를 지워버리면, 어디에서도 _hello를 찾을 수 없어서 에러가 발생합니다.



사실 "a.c"에서는 "a.h" 를 반드시 include할 필요는 없습니다만, 개인적으로 해 주는 것이 좋다고 생각합니다.
"a.c"를 다음과 같이 업데이트 한 상황을 생각해 봅시다. "a.h"는 실수로 고치지 않았습니다.

//#include "a.h"
 
void hello(int a)
{
	int i;
 
	for(i=0;i<a;i++) { printf("Hello World.\n"); }
}

_hello는 정상적으로 생성이 되지만 main 에서는 'void hello();' 처럼 사용하고 있습니다. 컴파일, 링크 모두 정상적으로 이루어지지만 런타임에 에러가 날 수 밖에 없는 상황입니다.

만약, 주석처리된 부분을 고쳐서

#include "a.h"
 
void hello(int a)
{
	int i;
 
	for(i=0;i<a;i++) { printf("Hello World.\n"); }
}

를 컴파일할 때,
선언 void hello(), 구현 void hello(int a) 의 불일치로 컴파일 과정에서 에러가 발생하므로,
"a.h"가 잘못되었다는 것을 즉시 파악하고, 바로 고칠 수 있습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.