static으로 선언된 함수를 헤더파일에 쓰면 경고가 나오네요..

superkkt의 이미지

#ifndef _HAVE_DATA_RECV_H
#define _HAVE_DATA_RECV_H

#include "kftp.h"
#include <stdio.h>

#define ACK_STRING	"HEADER_OK"
#define PREAMBLE	"TEST"

static char *err_msg[] = {
	"Invalid header message\n",
	"Header message receive error\n"
};

/*static char read_header(char *buf, struct file_info *filestat);
static void header_ack(FILE *fp, int sockfd);*/
void header_recv(struct file_info *filestat, int sockfd);
void data_recv(struct file_info *filestat, int sockfd);

#endif

위 헤더파일에서 주석처리된 두개의 함수는 해당 소스파일 안에서만 사용이 됩니다. 외부에서 접근할 필요가 없는 함수라서 static으로 선언을 했는데요..

컴파일할때 해당 소스파일만 단독으로 컴파일하면 아무런 경고도 안나오는데 다른 소스파일(위 헤더를 인클루드하는 파일)에서 컴파일을 하면 아래와 같은 경고가 나옵니다.

Quote:
data_recv.h:15: warning: 'read_header' declared `static' but never defined
data_recv.h:16: warning: 'header_ack' declared `static' but never defined

그래서 주석처리를 해주니 경고는 안나오는데.. 저렇게 내부에서만 사용하도록 static으로 선언한 함수들은 헤더파일에서도 프로토타입을 적어주면 안되는건가요?

cococo의 이미지

static으로 선언되면 당연히 에러이지 않을까...생각했는데 본문이 warning이라서 직접 해 보니, 제 쪽에서는 warning조차 안 나네요? 그냥 컴파일 되 버리는데요? 이런 황당한... -_-;;

소스 코듭니다. 이런 식으로 된 거 아닌가요?

--test2.c--

#include <stdio.h>
#include "test2.h"

int main()
{
	return 1;
}

static int Fn1()
{
	return 1;
}


--test2.h--

static int Fn1();


--test3.c--
#include "test2.h"

int Fn2()
{
	return 1;
}

거참... 어찌된 건지...전에 비슷하게 해서 에러 났었는데... -_-;;;;

sangwoo의 이미지

말씀하신 두 함수의 구현체(.c파일에 define된)와, 헤더 파일에 선언된 두 함수는 다른 함수로 취급됩니다. 그 이유는 static이기 때문에, 해당 파일로 scope가 한정되기 때문이지요.
따라서, 헤더 파일에는 해당 함수의 선언만 있고, 정의가 없기 때문에 warning이 나오는 것입니다.

PS. ...라고 생각합니다. -_-a 고수님들의 답변 부탁드립니다.

P.P.S
제가 위에 쓴 글에서 마지막 문장을 고쳐야 할 것 같습니다.

Quote:
따라서, 헤더 파일에는 해당 함수의 선언만 있고, 정의가 없기 때문에 warning이 나오는 것입니다.


헤더를 include 한 다른 .c 파일에는.... 으로 해야 할 것 같습니다. ^^

----
Let's shut up and code.

sangwoo의 이미지

ckbcorp wrote:
static으로 선언되면 당연히 에러이지 않을까...생각했는데 본문이 warning이라서 직접 해 보니, 제 쪽에서는 warning조차 안 나네요? 그냥 컴파일 되 버리는데요? 이런 황당한... -_-;;

소스 코듭니다. 이런 식으로 된 거 아닌가요?
[snip]

거참... 어찌된 건지...전에 비슷하게 해서 에러 났었는데... -_-;;;;

제가 해보니 warning이 납니다만 :-) -Wall을 빼고 컴파일하신 게 아닌가요?

swoo:~/tmp/static_warn $ gcc -c -Wall test3.c
test2.h:1: warning: 'Fn1' declared `static' but never defined

----
Let's shut up and code.

mirr의 이미지

http://groups.google.co.kr/group/han.comp.lang.c/browse_thread/thread/1379a0cc6bcfaa09/e4d2bec5b3076409?q=%60static'+but+never+defined&rnum=1#e4d2bec5b3076409

구글 han.comp.lang.c에서 찾아봤습니다..
대략 이런 글들이 있더군요..
제 컴파일러에서도 역시 워링한줄 뜨질 않았습니다....

하지만 제 생각에는 이 static이라는 키워드는 file scope의 제한을
갖고 있기때문에, header파일의 함수와, 소스파일의 함수를 서로 다른것으로
받아들여서 나온 경고같습니다.

내 마음속의 악마가 자꾸만 나를 부추겨.
늘 해왔던 것에 만족하지 말고 뭔가 불가능해 보이는 것을 하라고 말야.

superkkt의 이미지

몇가지 오픈소스 프로그램들 코드를 뒤져보니 static으로 선언된 함수의 프로토타입은 헤더파일에 넣지 않고 소스파일에만 있네요.. 통용범위 때문에 발생하는 문제가 맞는거 같습니다.

======================
BLOG : http://superkkt.com

doldori의 이미지

문법적으로만 본다면 선언 자체는 전혀 문제가 없으므로 경고는 무시해도 좋습니다.
그러나 선언의 의미를 따져볼 때 static 함수의 선언을 헤더에 넣는 것은 이치에 맞지
않기 때문에 똑똑한 컴파일러가 경고를 주는 것입니다.

일반적으로 헤더에 넣는 내용은 여러 소스가 공유해야 하는 정보입니다. 그리고
그 소스 파일들에서 사용되는 동일한 이름이 같은 대상을 가리키도록 하기 위한 것이
연결(linkage)이라는 개념입니다. 예를 들어 위의 헤더를 #include하는 여러 소스들은
header_recv라는 이름을 만나게 되고 각 소스를 컴파일하여 obj 파일로 만들 것입니다.
이제 여러 obj 파일에서 사용된 각각의 header_recv가 같은 함수를 가리키도록
해야 합니다. 이런 일을 하는 것이 linker죠. 이때 header_recv는 외부 연결(external
linkage)를 갖는다고 말합니다. 외부 연결을 갖는 개체의 선언에 쓰이는 extern
키워드가 이와 관련이 있는 것입니다.

그런데 블럭 외부의 static은 내부 연결(internal linkage)를 갖도록 하는 지정자입니다.
즉 static으로 선언된 것들은 여러 소스에서 사용되는 동일한 이름이 충돌을 일으키지
않고 사용할 수 있도록 하는 것입니다. (블럭 내부에서 개체의 기억 수명을 지정하기
위한 static과는 다른 의미입니다.)

이제 static 함수의 선언을 헤더에 넣는 것이 왜 의미가 없는 것인지 알 수 있습니다.
헤더에서 static 함수를 선언해봤자 그 헤더를 #include하는 소스에서는 같은 이름을
쓴다고 하더라도 실제로는 서로 별개의 대상을 지칭하고 있는 것입니다. 즉 애당초부터
여러 소스들이 그 이름을 공유할 이유가 없습니다. 따라서 static 개체는 헤더에 넣지
않고 .c 파일에서 선언/정의하는 것입니다.

ps. 블럭 외부의 선언에서 쓰이는 static은 통용 범위(scope)와는 무관합니다.

mirr의 이미지

오호...저도 자세하게 배웠네요..감사합니다..

내 마음속의 악마가 자꾸만 나를 부추겨.
늘 해왔던 것에 만족하지 말고 뭔가 불가능해 보이는 것을 하라고 말야.

수수깡의 이미지

g++ -fPIC -Wall -Wshadow (...)
으로 컴파일 해보세요.. 그러면 워닝이 날꺼에요 ...ㅋㅋ :)

그리고 .cpp에 넣어도 같은 워닝이 납니다. ^___^;;
제가 알고 있는건 static을 함수원형에 썼을때 워닝이 난다는 겁니다.
static은 함수정의부분에 있어야 워닝이 안납니다.

음.. 그런데 이렇게 까지 워닝을 없애야 할 필요가 있을까요~?

THe World is just awesome~!!
http://susukang.tistory.com

powerson의 이미지

위에서 어떤 분이 말씀하셨다시피 static은 file scope를 갖기 위해서 사용하는 것인데, header에 넣으시면, 해당 header를 include할 때마다 해당 source의 scope에도 함수 원형은 들어갔지만, 함수 정의되어 있는 source 외에는 그 이외의 source에서는 전혀 알 수 없는 함수 이므로, 당연히 warning이 나야 되는게 정상이라고 봅니다. 저렇게 header에 넣어서 사용하실 거면, 해당 source에 대한 file scope를 갖지 않는다고 생각할 수 있기 때문에, 오히려 extern이 맞겠지요.

------------------------------------------------------
아직은 젊다. 모든 것을 할 수 있는 나이란 말이지.

------------------------------------------------------
아직은 젊다. 모든 것을 할 수 있는 나이란 말이지.

댓글 달기

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