짜투리

[static] static? 그게 뭔데 씹덕아;;

소곡이 2023. 3. 10. 13:29
728x90

 

 

나와쪄!


 1학년 C 수업 듣고 있다. 몇 십년만에 hello world를 치니까 새로웠다.

 

 내 주언어는 파이썬이고, 재작년 1학기 자료구조, 2학기 C프젝 들은 이후로 C는 오랜 만이다. 게다가 C를 독학한 거라 코드는 칠 줄은 알지만 정확히 어떻게 돌아가는지는 잘 모르는 상태라 흥미롭게 수업 듣고 있다. 

 

 물론 진도가 굉장히 느림. 1학년 친구들이 printf를 Printf로 쓰고, 실행 파일 찾으라니까 헤매고 있어서 교수님이 샤우팅하시는 거 몇 번 듣다가. 이렇게 된 이상 C언어를 다시 공부해봐야겠다! 하면서 혼자만의 여행을 떠났다. 

 

 for문 어케 쳤더라 하면서 구글링 한 번하고. hello world를 쳤다가, C언어에서 문자열 다루기가 힘들었던 기억이 나서 함수로 만드는 과정을 공부했다. 

 


코드 

#include<stdio.h>  //standard input output, 라이브러리(개발자가 만들어 놓은 것)

char* string() {
	static char str[50] = "Hello World!"; // 꼭 static을 붙여줘야 함
	return str;
}

int main() {
	printf("%s", string());

	return 0;
}

 

포인트

  • 문자열을 입력할 때는 배열을 사용해야 함
  • 문자열을 반환할 때는 포인터를 사용해야 함
  • 함수 내에서 정의한 문자열을 외부에서도 쓰고 싶다면 static으로 정의해야 함

 


뭔 개소리야?

1. 문자열을 입력할 때는 배열을 사용해야 함

char str[50] = "Hello World!";
  • 파이썬에서는 자료형이 자동할당되기 때문에 자료형을 붙여줄 필요가 없다
  • C에서는 자료형을 명시적으로 써야 한다
  • 하지만 문자열에 관한 자료형은 없다
  • 그래서 char(문자) 자료형을 쓴다
  • 문자열은 문자들의 모임으로, char에 저장할 수 없다
  • 그래서 char 자료형을 가지는 배열에 문자를 하나씩 저장하는 거다! 

 

2. 문자열을 반환할 때는 포인터를 사용해야 함

char* string()
  • string 함수를 보면 반환형이 포인터인 걸 알 수 있다
  • 알다시피 변수는 하나의 값만 저장할 수 있다
  • 그래서 배열의 첫번째 주소를 가리키는 값(포인터)을 저장하는 것이다

 

3. 함수 내에서 정의한 문자열을 외부에서도 쓰고 싶다면 static으로 정의해야 함

static char str[50] = "Hello World!"; // 꼭 static을 붙여줘야 함

 

  • static은 정적 변수를 선언할 때 사용된다
  • static으로 선언한 값은 메모리에 딱 한 번 생성 된다
  • 때문에 함수를 실행시킨 이후에 다른 함수에서도 접근이 가능하다(왜냐면 메모리에 이미 정의되어 있으니까)

추가 설명

1. static

 static 키워드는 일반적으로 정적 변수, 정적 메소드를 선언할 때 사용된다. 만약 클래스 내부에서 static으로 선언된 변수나 메소드가 있다면 그 클래스는 모든 인스턴스가 공유하는 값이 된다. 

 

 위를 예시로 들자면 static 변수 즉, str은 프로그램이 처음 실행될 때 한 번만 생성되고 유지된다. 

 

 또, 만약 클래스 내부에 static 변수 혹은 메소드가 있다면. 그 변수와 메소드는 객체를 선언하지 않아도 사용할 수 있다. 왜냐면 이미 메모리에 정의 되어 있으니까!

 

2. 유틸리티 클래스와 static

 유틸리티 클래스는 유용한 기능을 제공하기 위해 만들어진 클래스이다. 보통 정적 변수와 정적 메소드만 가지고 있다. 예를 들어, Math클래스 등이 있다. 

 

3. 파이썬 @classmethod와 static

 static의 개념을 잘 모르고 있었는데, 공부하면서 보니 파이썬의 @classmethod와 매우 유사한 것이다. 

 

 파이썬 @classmethod는 클래스 메소드(객체 모두가 공유하는 메소드)를 정의할 때 사용되며, 첫번째 인자로 cls인자를 사용할 수 있다. cls는 클래스 메서드가 속한 클래스 자체를 참조하는 인자이다. 

 

 동작은 비슷하나 파이썬의 @classmethod는 첫번째 인자로 클래스 자체를 받아서 클래스 메소드를 호출할 수 있도록 지원하는 반면, static은 클래스 자체를 인자로 받지 않고, 클래스 레벨에서 정의된 메서드나 변수를 참조할 수 있도록 하는 키워드이다. 

 


(+추가)

  • 이 게시물을 보시곤 static은 자바로 설명하는 게 정석이라고 말씀해주신 블랙캣 님 감사합니다. 
  • 참고자료: 명품 자바 프로그래밍

1. non-static 멤버 vs static 멤버

non-static 멤버(=인스턴스 멤버)  static 멤버(=클래스 멤버)
객체 생성 시에 멤버 생성 됨 객체를 생성하지 않고도 사용할 수 있는 멤버
main() 메소드 실행되기 전에 이미 생성 됨
객체 간 공유되지 않음 동일한 클래스의 모든 객체들에 의해 공유됨

 

2. 자바에서 static 멤버의 생성과 활용

class StaticTest{
    // non-static
    public int n;
    public void g(){
    	m=20;
    }
    
    // static
    public static int m;
    public static void f() P
    	m=5;
    }
}
  • 여기서 static 멤버인 m과 f()는 두 아래 객체가 생성되기도 이전에 이미 생성되어 있음
public class ex{
	public static void main(String[] args){
    	StaticTest s1;
        s1 = new StaticTest();
        s1.n = 5;
        s1.g();
        s1.m = 50;  // static
        s1.f(); //static
     }
}

 

  • static 멤버는 클래스당 하나만 있기 때문에 클래스이름으로도 바로 접근할 수 있음
StaticTest.m = 10;
StaticTest.f();

 

3. static 특징

1. 자바에서는 어떤 변수나 함수도 클래스 밖에 존재할 수 없음(자바의 캡슐화)

  • so, 모든 클래스에서 호출할 수 있는 전역 함수, 전역 변수가 필요한 경우 사용됨(ex. java.lang.Math)
Math m = new Math(); // 오류: 생성자 Math()는 private으로 선언되어 있어 객체 생성 안 됨
int n =m.abs(-5);
int n = Math.abs(-5);

2. static 메소드는 static 멤버만 접근할 수 있음

  • 객체가 생성되지 않아도 사용가능하므로, 인스턴스 변수가 없는 상황이거나 많은 상황 어떤 변수에 접근해야 할 지 모르기 때

3. static 메소드는 this를 사용할 수 없음

  • 위와 마찬가지 이유로 객체 없이 존재하기 때문임

 

(번외)

- this?: 객체 자신에 대한 레퍼런스.

  • 파이썬으로 치면 self

 


 다음에는 파이썬 classmethod와 java의 classmethod 차이점도 알아보겠다.

 

끗~