C언어에서 블럭내 내부연결을 가지는 변수를 선언하려면!?
글쓴이: gurumong / 작성시간: 월, 2006/11/20 - 5:57오후
안녕하세요 ^^
C언어를 공부하는데 궁금한점이 있습니다
딱히 주위에 물어볼만한곳이 여기 말고는 없네요 ^^;
블럭통용범위 내에서 대상체를 내부연결로 선언하려면 아래와 같이
그 이전에 파일통용범위에서 내부연결로 선언후 정작 블럭내에서는 "외부"연결로 선언해서
이전 블럭통용범위에서의 내부 선언을 이어받아 내부 연결이 되게 해야하는것이 맞습니까?
내부 연결을 갖게 하도록 하기 위해 기억부류 지정자 extern을 써야한다니, 오히려 static로 선언하면 새로운 연결없는 대상체가 선언되고, 제가 제대로 이해한건지 의구심이 들어 질문을 했습니다
static int var; /* 내부 연결 */ main () { { extern int var; /* 내부 연결 */ } }
Forums:
잘못 알고 계십니다.
완전히 잘못 알고 계셔서 어떻게 설명을 들여야 할지 모르겠네요.
static 은 file 내 연결을 갖습니다.
함수 밖에서 static 으로 선언을 했다는 것은 다른 C source file 에서
같은 이름으로 선언된 것과 충둘을 일으키지 않기 위해 사용됩니다.
달리 말하면 file 내에서 함수 밖에서 선언된 static 은 여전히 어떤 함수에서도 접근할 수 있습니다.
Block 내 통용범위선언은 그 block 안에서 선언하시면 됩니다.
[device 님께] >
[device 님께]
> 블럭통용범위 내에서 대상체를 내부연결로 선언하려면 아래와 같이
> 그 이전에 파일통용범위에서 내부연결로 선언후 정작 블럭내에서는 "외부"연결로 선언해서
> 이전 블럭통용범위에서의 내부 선언을 이어받아 내부 연결이 되게 해야하는것이 맞습니까?
>
> 내부 연결을 갖게 하도록 하기 위해 기억부류 지정자 extern을 써야한다니, 오히려 static로 선언하면 새로운 연결없는 대상체가 선언되고, 제가 제대로 이해한건지 의구심이 들어 질문을 했습니다
>
> static int var; /* 내부 연결 */
>
> main ()
> {
> {
> extern int var; /* 내부 연결 */
> }
> }
>
핵심적인 부분은 맞게 이해하셨습니다.
"정작 블록내에서는 외부 연결로 선언해서"라고 이해하시는 것보다 "extern
이 항상 외부 연결을 의미하는 것은 아니다" 라고 이해하시는 편이 더 쉽지
않을까 생각합니다.
물론, 이미 같은 소스 파일 내에서 파일 통용범위로 선언된 명칭을 굳이
블록 안에서 다시 선언할 "실용적"인 이유는 존재하지 않겠지요.
extern 의 경우와 마찬가지로 static 이 항상 "내부 연결"을 의미하는 것이
아닙니다. 즉, static 이라는 하나의 키워드가 언어 내에서 중의적으로
사용되고 있다는 것입니다. static/extern (특히나 static) 이 문맥에 따라
다양한 의미와 기능으로 갖는다고 이해하시면 보다 편안히 받아들이실 수
있으리라 생각합니다.
main() 함수의 정의 형태에 대해서는 일부러 간략하게 적으신 것이라 판단
하고 따로 말씀드리지 않겠습니다.
[winner 님께]
> static 은 file 내 연결을 갖습니다.
>
그렇지 않습니다. 만약 static 이 항상 file 내 연결(내부 연결)을
의미한다면 왜 블록 내의 함수 선언에 static 을 붙일 수 없도록 하고
있을까요?
> 함수 밖에서 static 으로 선언을 했다는 것은 다른 C source file 에서
> 같은 이름으로 선언된 것과 충둘을 일으키지 않기 위해 사용됩니다.
>
a.c 에서 very_common_name 을 static 으로(내부 연결로) 선언하고, b.c
에서 very_common_name 을 extern 으로(외부 연결로) 선언하면 언어 정의에
따라 어떻게 될까요? 많은 분들이 file scope 명칭일지라도 static 만
붙이면 전혀 다른 파일(모듈)의 간섭을 받지 않는다는 착각을 하고 계신 것
같습니다. name space 구분 조차 프로그래머가 해주어야 하는 C 언어, 그리
사용하기 편한 언어는 아닙니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
완전히 잘못 알고 있는 것은 나?
그런데 블록 내 함수선언이라 하면 C99 에서 추가된 부분이 맞나요?
int main(void) {
Comeaucomputing C compiler 왈:
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
선언(declaration)과 정의(definition) 그리고 사용(use)
>a.c 에서 very_common_name 을 static 으로(내부 연결로) 선언하고, b.c
>에서 very_common_name 을 extern 으로(외부 연결로) 선언하면 언어 정의에
>따라 어떻게 될까요? 많은 분들이 file scope 명칭일지라도 static 만
>붙이면 전혀 다른 파일(모듈)의 간섭을 받지 않는다는 착각을 하고 계신 것
>같습니다.
선언상에서는 문제가 없습니다만, 변수를 사용하기 시작하면 문제가 발생합니다.
static은 번역단위내에서만 연결을 갖게끔 한정된 속성입니다.
넵, 제가 말씀드리고
넵, 제가 말씀드리고 싶은 점은 static 으로 내부 연결로 선언했다는
이유만으로 함수명, 변수명을 큰 고민 없이 정해서 사용한다는 것입니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
답변 감사합니다 ^^
흠, 그렇다면 예에서 보인 저런 선언이 정상적인거군요 ^^
어떤 책에서의 static, extern 설명이 머리에 박혀있어서..
전웅님의 "항상...의미하는것은 아니다" 라는 답변을 읽고 조금 감이 오는게 있네요
아 그리고 main함수 정의에서 반환형 int을 빼먹은게 맞지요?
간략하게 적으려고 하긴 했지만 그렇다고 잘못된 코드를 적으려고 했던건 아닌데 T.T
답변 해주시는 여러 분들 감사합니다 (__)
반환형 int 와, C90 을
반환형 int 와, C90 을 생각하신다면 return 0; 도
포함입니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
이해가 안가는 점이 있어서...
라고 하면 gcc 에서는 문제없이 compile 이 됩니다.
이것은 표준에 어긋나는 code 인가요?
a.c 에서의 a 함수의 정의를 main 함수 밑에 두면 non-static 선언이 나온 후
static 선언이 나온다며 오류를 냅니다.
a.c 에서는 a 함수의 선언이 main 함수가 끝나면서 통용범위가 끝나는 것 아닌가요?
그 후 static 으로 정의된 a 함수가 왜 오류가 되는 거죠?
a.c 에서 main 밑 a 함수 없이 b 함수를 정의하고 b 함수에서 a 를 호출하면
묵시적 선언이라고 합니다. 그렇다면 함수내 함수선언은 역시 block 통용범위를 갖는다는 것인데...
이 세가지를 어떻게 이해해야 하는지 알 수가 없군요.
This link
http://kin.naver.com/db/detail.php?d1id=1&dir_id=10104&eid=XDiLL9ttU8fRMXAz5b3OXpsrHwmiNCfh&qb=c3RhdGlj
이글이 맘에 드는데...
> > a.c >
>
> a.c
> -----------------
> static void a(void)
> {
> }
>
내부 연결로 정의되었으며, scope 은 file scope 입니다.
> int main(void)
> {
> void a(void);
현재 scope 내에 보이는 선언의 연결을 물려 받습니다. 따라서 내부 연결
선언이며, scope 은 block scope 입니다.
> a();
> return 0;
> }
>
> b.c
> ----------------
> void a(void)
> {
> }
>
분리된 translation unit 에서 외부 연결로 정의되었습니다.
>
> 라고 하면 gcc 에서는 문제없이 compile 이 됩니다.
> 이것은 표준에 어긋나는 code 인가요?
>
네 그렇습니다. 익히 알고 계신 사실이겠지만, 컴파일러가 표준을 위반한
모든 코드를 잡아줄 필요도, 그럴 수도 없습니다.
>
> a.c 에서의 a 함수의 정의를 main 함수 밑에 두면 non-static 선언이 나온 후
> static 선언이 나온다며 오류를 냅니다.
>
> a.c 에서는 a 함수의 선언이 main 함수가 끝나면서 통용범위가 끝나는 것 아닌가요?
> 그 후 static 으로 정의된 a 함수가 왜 오류가 되는 거죠?
>
원칙적으로 a 함수의 정의가 a.c 에서 main 함수 밑으로 가면, a 함수 안의
선언은 외부 연결 선언이고 scope 은 block scope 을 갖습니다. 따라서
main 함수 밖에서는 영향력이 사라지고 그 밑에서 a 함수가 내부 연결로
정의되게 됩니다. 하지만, 이런 구조는 하나의 명칭을 외부/내부 연결로
선언하고 있는 셈이므로 undefined behavior 가 됩니다. 따라서 잘못된
프로그램에 대해 잡아주는 것이 정당해지는 것입니다.
별로 보기 싫으실지도 모르겠지만, 제 책을 보시면 연결에 대한 이와 같은
내용이 나와 있습니다.
p.s. 익명사용자님이 인용하신 링크는 관련없는 내용일뿐 아니라 잘못된
내용도 포함하고 있습니다. 지식인은 생활 지식 검색용이 딱인듯
싶습니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
의미적 오류로 해석해야 하지 않을까요?
>>
>> 라고 하면 gcc 에서는 문제없이 compile 이 됩니다.
>> 이것은 표준에 어긋나는 code 인가요?
>>
>
>네 그렇습니다. 익히 알고 계신 사실이겠지만, 컴파일러가 표준을 위반한
>모든 코드를 잡아줄 필요도, 그럴 수도 없습니다.
표준에 위배된 부분은 없습니다. 단지 의미적인 오류(b.c의 a함수는 사용되지 않았다)라는 사실 뿐입니다.
// 즉, a.c에서는 b.c의 a함수를 사용할 수 없다는 사실 뿐입니다.
// 사용하고 싶다면, 두 함수 중 하나는 rename을 해야 합니다.
// 또는, wrapper용 함수를 하나 만들 수도 있을 것 같습니다.
> >> > >> 라고 하면 gcc
> >>
> >> 라고 하면 gcc 에서는 문제없이 compile 이 됩니다.
> >> 이것은 표준에 어긋나는 code 인가요?
> >>
> >
> >네 그렇습니다. 익히 알고 계신 사실이겠지만, 컴파일러가 표준을 위반한
> >모든 코드를 잡아줄 필요도, 그럴 수도 없습니다.
>
> 표준에 위배된 부분은 없습니다. 단지 의미적인 오류(b.c의 a함수는 사용되지 않았다)라는 사실 뿐입니다.
> // 즉, a.c에서는 b.c의 a함수를 사용할 수 없다는 사실 뿐입니다.
> // 사용하고 싶다면, 두 함수 중 하나는 rename을 해야 합니다.
> // 또는, wrapper용 함수를 하나 만들 수도 있을 것 같습니다.
>
이 프로그램의 종료 상태값 (main 함수의 반환값) 은 무엇일까요? 표준에
따르면 무엇이 되어야 할까요?
lovewar 님께서 잘못 알고 계십니다. 제가 애초에 a.c, b.c 를 언급하며
예를 들었을 때 전달하고자 했던 이야기가 바로 이것입니다. 동일한 명칭
이 동일한 namespace 에서 한 translation unit 에서 내부 연결로, 다른
translation unit 에서 외부 연결로 선언되어 사용되는 경우 그 "자체"만
으로 "잘못된" 프로그램이 된다는 것입니다. 적지 않은 분들이 단순히
명칭에 접근만이 불가능할 것이라 생각하는데, 엄밀한 의미에서는 그렇지
않습니다. 결국 winner 님이 보여주신 프로그램도, 제가 위에 적은
프로그램도 "잘못된" 프로그램입니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
표준을 확실히 모르기에
>이 프로그램의 종료 상태값 (main 함수의 반환값) 은 무엇일까요? 표준에
>따르면 무엇이 되어야 할까요?
제시하신 코드는 표준 위배코드(컴파일 오류)를 발생해야 합니다.
C90에서 묵시적 선언(extern int identifier())으로 보고 있기 때문입니다.
제가 이야기 하고 있는 근거는 C99(6.2.2 Linkages of identifiers)의 다음 문장입니다.
>동일한 명칭이 동일한 namespace 에서 한 translation unit 에서 내부 연결로, 다른
>translation unit 에서 외부 연결로 선언되어 사용되는 경우 그 "자체"만
>으로 "잘못된" 프로그램이 된다는 것입니다.
제가 보는 관점의 변수와 함수의 namespace는 다음과 같습니다.
잘못된 부분이 있으면 바로 잡아 주시기 바랍니다.
번역단위 집합, 함수 단위집합(블럭단위), 그리고 전체 집합(linkage), 이렇게 3분류로 나눠져야 하지 않을까 생각합니다.
> >이 프로그램의
> >이 프로그램의 종료 상태값 (main 함수의 반환값) 은 무엇일까요? 표준에
> >따르면 무엇이 되어야 할까요?
>
> 제시하신 코드는 표준 위배코드(컴파일 오류)를 발생해야 합니다.
>
표준은 잘못된 코드에 대해 컴파일 오류를 발생하도록 요구하지 않습니다.
유일하게 #error 을 사용한 경우에 대해서만 컴파일을 중지하도록 요구
하고 있을 뿐입니다. 적절한 진단 메시지만 출력한다면 포트란 프로그램을
올바르게 번역, 실행해 주어도 무관합니다.
> C90에서 묵시적 선언(extern int identifier())으로 보고 있기 때문입니다.
>
C90 의 implicit declaration 이 "C90 에서는" 잘못된 구조가 아닙니다.
> 제가 이야기 하고 있는 근거는 C99(6.2.2 Linkages of identifiers)의 다음 문장입니다.
>
> 인용:
>
> In the set of translation units and libraries that constitutes an entire program, each
> declaration of a particular identifier with external linkage denotes the same object or
> function. Within one translation unit, each declaration of an identifier with internal
> linkage denotes the same object or function. Each declaration of an identifier with no
> linkage denotes a unique entity.
>
그 아래(맞나? 기억이.. --;) 외부 연결을 가진 명칭에 대한 문단도 읽어
보시길 추천합니다. 근거를 원하신다면 그곳에서 찾으실 수 있습니다.
> >동일한 명칭이 동일한 namespace 에서 한 translation unit 에서 내부 연결로, 다른
> >translation unit 에서 외부 연결로 선언되어 사용되는 경우 그 "자체"만
> >으로 "잘못된" 프로그램이 된다는 것입니다.
>
> 제가 보는 관점의 변수와 함수의 namespace는 다음과 같습니다.
>
표준이 정의해 사용하는 용어를 개인적인 관점으로 재해석 하실 경우
의사소통이 불가능합니다.
표준에서 말하는 namespace 는 서로 동일한 명칭이 서로 간섭 없이 쓰일 수
있는 공간을 말합니다 - 일반 명칭, label 명, 구조체 공용체 열거의 tag,
각 구조체 공용체의 멤버명이 이에 해당됩니다.
>
>번역단위 집합, 함수 단위집합(블럭단위), 그리고 전체 집합(linkage), 이렇게 3분류로 나눠져야 하지 않을까 생각합니다.
>
표준 어디서도 명칭을 이렇게 나누는 개념은 없습니다 - 또한, 그럴 수도
없습니다 (모든 명칭이 저 세가지 분류 안에 들어갈 수는 없습니다).
말씀하신 분류는 scope 와 linkage 를 기준 없이 섞어 놓은 것에 해당
합니다.
표준을 인용하며 논의할 때는 표준이 정의하고 사용하는 개념과 용어를
사용하는 것이 올바른 방법이 아닌가 생각합니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
좋은글 감사합니다.
유일한 식별자를 정의해야 한다라고 만 하면 될 것 linkage의 개념을 두었는지 의문이 생깁니다.
// 단지 extern 개념 하나만으로도 되지 않을까란 생각이 듭니다.
혹시 이부분에 설명(? 의견) 좀 부탁드립니다.
질문이 무슨 뜻인지
질문이 무슨 뜻인지 모르겠습니다. linkage 개념이 필요없다는
것을 주장하고 계신 것인지요? 어떻게 했으면 될 것이다.. 라고
정확히 적어주신다면 어느 부분이 문제가 되는지 좀 더 쉽게
파악할 수 있을 것 같습니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
internal linkage 성격과 유일한 식별자란 관점에서
internal linkage(static)의 역할에 대한 의문이 생깁니다.
//유일한 식별자를 정의하기 위해서는 internal linkage의 역할이 필요 없고,
// external linkage 만을 사용해도 충분하다는 겁니다.
>동일한 명칭 이 동일한 namespace 에서 한 translation unit 에서 내부 연결로, 다른
>translation unit 에서 외부 연결로 선언되어 사용되는 경우 그 "자체"만 으로 "잘못된" 프로그램이 된다는 것입니다.
왜 내부 연결이 있어야 하나요? 에 대한 설명좀 부탁드립니다(위 내용에서 그런 궁금증이 생깁니다).
> internal
> internal linkage(static)의 역할에 대한 의문이 생깁니다.
> //유일한 식별자를 정의하기 위해서는 internal linkage의 역할이 필요 없고,
> // external linkage 만을 사용해도 충분하다는 겁니다.
>
> >동일한 명칭 이 동일한 namespace 에서 한 translation unit 에서 내부 연결로, 다른
> >translation unit 에서 외부 연결로 선언되어 사용되는 경우 그 "자체"만 으로 "잘못된" 프로그램이 된다는 것입니다.
>
> 왜 내부 연결이 있어야 하나요? 에 대한 설명좀 부탁드립니다(위 내용에서 그런 궁금증이 생깁니다).
>
아... 이제야 문제의 요지를 알았습니다.
아래 프로그램은 올바른 프로그램입니다 - internal linkage 가 적절하게
사용되고 있는 예입니다.
저도 처음에는 내부 연결을 가진 명칭이 항상 외부 연결을 가진 명칭을
해당 translation unit 안에서 숨기기 때문에 이전 글에서 말씀하신 논리
적인 문제만이 있을 뿐, 표준 위반과 관련된 문제는 없다고 생각했습니다.
실제 대부분의 컴파일러 구현을 고려하면 이전에 잘못되었다고 보여드린
프로그램들이 오작동할 이유가 없습니다.
하지만 몇년전 프로그램 내에 내부 연결을 갖는 main 함수를 별도로 둘 수
있느냐는 고민을 진행하다가 (첨에는 위와 같은 생각에 기반해 그러한
프로그램도 문제가 없다고 판단했었습니다) 표준이 이를 허락하지 않는다는
사실을 알게 된 것입니다.
(제가 사용해본 컴파일러/링커의 행동을 고려했을 때) 다소 의외이며
불만족스러운 부분이긴 하지만, 보다 다양한 구현체를 반영하기 위한
결정이 아니었나 생각하고 있습니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
감사합니다.
달리 표현할 말이 생각나지 않아 짧게 인사합니다. 감사합니다.
추후 유사한 논의를
추후 유사한 논의를 계기로 comp.std.c 뉴스그룹을 통해 내부연결 명칭을
통해 외부연결 명칭을 숨길 수 있도록 하는 것이 표준의 "의도"라는 사실을
확인하였습니다 - 이는 표준에 문제가 있을 수 있음을 의미합니다. 보다
자세한 내용은
http://kldp.org/node/80188
를 참고하시기 바랍니다.
--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)
--
Jun, Woong (woong at gmail.com)
http://www.woong.org
댓글 달기