C에서 static variable과 static function의 차이를 알고싶습니다.

dlffjddlek00의 이미지

명확하게 질문하자면, static variable의 경우 해당 variable의 pointer를 써도 다른 file에서는 access할 수 없지만
static function의 경우 function pointer를 통해 다른 file에서도 접근할 수 있다고 배웠습니다.
도대체 그 이유가 무엇인가요? variable과 function이 memory 상에서 어떻게 다르게 저장되기 때문에 이런 일이 발생하는지 궁금합니다.

익명 사용자의 이미지

Quote:
static variable의 경우 해당 variable의 pointer를 써도 다른 file에서는 access할 수 없지만

아닙니다

Quote:
static function의 경우 function pointer를 통해 다른 file에서도 접근할 수 있다고 배웠습니다.

이건 맞습니다.

엄밀히 따져보면 복잡하긴 할 텐데... 일단 storage duration을 넘기지만 않았으면 포인터를 들고 가서 참조하는 건 문제가 없어요. 같은 주소공간 안이라면 말이죠.

익명 사용자의 이미지

혹시나 해서 여쭙습니다만 말씀하시는 file이 source file, 그러니까 translation unit 말씀하시는 거 맞죠?

dlffjddlek00의 이미지

program 내의 single source file을 말하는 것입니다. 그런데 static variable을 다른 file에서 접근할 수 있나요?
접근 하려고 하면 error가 나지 않나요?

익명 사용자의 이미지

직접 해 보면 금방 알 수 있지요

main.c:

#include <stdio.h>
#include "other.h"
 
int main(){
    struct ptr_to_static_t ptr_to_static = ftn();
 
    puts(__func__);
    printf("\tstatic_var : %d\n", *ptr_to_static.p_static_var);
    *ptr_to_static.p_static_var = 42;
    (*ptr_to_static.p_static_ftn)(__func__);
 
    ftn();
 
    return 0;
}

other.h:

#ifndef __OTHER_H__
#define __OTHER_H__
 
struct ptr_to_static_t{
    int *p_static_var;
    void (*p_static_ftn)(const char *);
};
 
struct ptr_to_static_t ftn();
 
#endif

other.c:

#include <stdio.h>
#include "other.h"
 
static int static_var = -42;
 
static void static_ftn(const char *from){
    printf("\tstatic_ftn called by %s\n", from);
}
 
struct ptr_to_static_t ftn(){
    puts(__func__);
    printf("\tstatic_var : %d\n", static_var);
    static_ftn(__func__);
 
    return (struct ptr_to_static_t){
        .p_static_var = &static_var,
        .p_static_ftn = &static_ftn
    };
}

빌드 환경: x86_64, Ubuntu 16.04.6 LTS, gcc (GCC) 8.2.0
빌드 명령어: gcc -std=c99 -pedantic -pedantic-errors main.c other.c -o static_test

경고/에러 없음. 실행 결과:

ftn
	static_var : -42
	static_ftn called by ftn
main
	static_var : -42
	static_ftn called by main
ftn
	static_var : 42
	static_ftn called by ftn

Any problem?

dlffjddlek00의 이미지

직접 프로그래밍을 하기 어려운 환경에 있어서 해보지 않고 질문한 점 죄송합니다ㅠㅠㅠ
제가 책을 완전히 오독한 것 같습니다! static function을 다른 file에서 access할 때 당연히 헤더파일로 prototype을 줘야 하는 건데, 책에는 자세한 설명없이 "function pointer을 쓰면 다른 file에서도 access할 수 있다"라고만 나와있고 static variable 부분에서는 아무 언급도 없어서 저는 variable과 다르게 function의 경우에는 prototype을 주지 않고도 access할 수 있다고 생각한 것 같습니다.
정말 귀찮으셨을텐데 이렇게 답변해주셔서 감사합니다!

그리고.. 가능하다면 하나만 더 답변해주실 수 있을까요? storage duration을 넘기지만 않았으면 pointer를 사용한 접근은 문제 없다고 하셨는데, scope rule도 영향을 끼치지 않나요? block scope인 variable에 대한 block 바깥에서의 pointer 접근은 불가능하지 않나요?

karkayan의 이미지

storage duration이 바로 그런 것을 말하는 것입니다.

bushi의 이미지

이게 이렇게 긴 질문과 긴 답변이 필요한 주제인지 호기심이 생기네요.

static variable 의 포인터를 다른 파일의 함수에서 참조할 수 없다면, printf() 로 문자열 출력하는 것 조차도 불가능합니다.

댓글 달기

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