C언어에서 include 관련 질문입니다.

thumbup7의 이미지

안녕하세요.
저는 현재 stm32f103 을 사용하여서 keil uVision 에서 프로그램을 짜는중입니다.
오늘 불현듯 질문 사항이 생겨서 질문을 남겨봅니다.

예전에 c++로 프로그램을 제작할때는 이런 궁금증이 생길 일이 없어지만
c를 하면서 가끔 multiple definition of ~ 이런식의 중복정의 에러를 많이 보는데요..
처음에는 고생을 상당히 많이 했습니다.

함수같은 경우야..

====test.c====
void sum(void)
{
//연산을 수행한다.
}

====test.h====
void sum(void);

위와같이 test.c과 test.h 에서 sum 이라는 함수를 수행할 수 있도록 만들어 주고서...

====Main.c====
sum(); //함수를 실행하는 것!!

이런식으로 함수를 다른 c에서 사용하는건 문제가 안되겠지만..

전역변수를 다른곳에서 사용 할 경우가 문제인데요.

====sub1.h====
int test;

====main.c====
#include "sub1.h"

extern int test;

test = 0;
=============

변수같은경우 다른 함수에서 사용하기위해서는 extern 을 이용한 방법은
위와 같이 사용 하는 경우라고 생각을 하는데..

인크루드 가드를 사용하고 해도 의미없게 multiple difinition 에러가 발생하는 경우가 있습니다.
위와 같이 단순하게 쓰는게 아니라

====sub1.h====
#include "sub3.h"
int test1;

====sub1.h====
#include "sub3.h"
int test2;

====main.c====
#include "sub1.h"
#include "sub2.h"

extern int test;

test = 0;

===============

이런식으로 위와 같이 사용하면 중복정의 에러가 뜨던데..

그래서 보통 다른 파일에서 사용할 때

=====test.c=====
int test;

=====test.h=====
extern int test; 라고 하고서

=====main.c=====
#include "test.h"
test=1;
================

위와 같이 사용은 하는데.. extern 을 저렇게 사용하는게아니라 이 질문 글의 맨 위에 처럼 사용하는게 맞는거같은데... 혼란스럽네요...

가끔 중복정의 에러로 인하여 그거 찾으러 다닌다고 고생하다보니..
확실하게 원인 분석을 하고싶어서... 질문글 남깁니다..

번외 질문으로는
저는 보통 c 파일에서만 다른 헤더파일을 include 하는데요..
h파일에서 다른 헤더파일을 include 해도 되는건가요..?

c 파일에서 다른 헤더가필요하면 c에서 인크루드하고 h에서 다른 헤더가 필요하면 h에서 인크루드
그리고 c와 h 둘다에서 필요하면 h에서 include 하는데요...

음.. 두서없는 질문이지만.. 답변 기다려볼게요....
감사합니다..

peecky의 이미지

1.
헤더파일에 변수를 선언하면, 해당 해더파일을 인클루드하는 모든 c 파일이 그 변수를 선언하는 효과가 나타납니다.
c파일에 변수를 선언하고, 그 변수를 사용하는 c파일에 extern으로 해당 변수를 볼 수 있게 해주면 됩니다.

말씀하신 것 처럼,

=====test.h=====
extern int test;

=====test.c=====
int test;

=====main.c=====
#include "test.h"
test=1;
================

형식으로 해도 되고, 아니면

=====test.h=====

=====test.c=====
int test;

=====main.c=====
#include "test.h"
extern int test;
test=1;
================

처럼 해도 됩니다.

2.
(인클루드 가드가 잘 동작한다는 가정 하에)
헤더파일에서 다른 헤더파일을 인클루드 해도 됩니다.
헤더파일 안에서 다른 헤더파일의 내용에 대한 의존성이 있으면 가급적 인클루드 해주는 것이 좋습니다.
h파일과 c파일 둘 다 같은 헤더파일에 의존성이 있으면 양쪽에서 인클루드를 하는 것이 좋습니다.

thumbup7의 이미지

일이 있어서 답글을 늦게 보게 되었습니다.
간단명료하게 정리해주셔서 감사합니다.

추가적인 질문 덧붙이겠습니다..
##########################
형식으로 해도 되고, 아니면

=====test.h=====

=====test.c=====
int test;

=====main.c=====
#include "test.h"
extern int test;
test=1;
================

처럼 해도 됩니다.
##########################

위와 같은 부분에서
test 라는 변수는 test.c 에 선언 되어있고
test.h에는 빈칸인데 main.c에서는 test.h 를 인클루드 해도
test변수에 접근이 가능한것인가요..?
저럴 경우에는 main.c가 test.c 를 인클루드 해줘야하는건지요..?

그리고 추가로
인클루드 가드가 제대로 동작되는지 안되는지 알 수가 없습니다.
중복 선언되었다는 명령어가 자주 뜨는데
혹시 인클루드가드가 동작여부를 확인하는 방법이 있을까요?

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.