Scope

  • 코드 블럭의 유효 범위
  • int main(){ // <- main scope 
    }
     
    int fn(){ // <- fn function scope
        int a = 0;
        
        if (true){ // <- if block scope
      	  int a = 1;
        }
        
        { // <- block scope
      	  int a = 2;
        }
    }

지역 변수

  • 저장 위치
  • 생명주기
    • 함수/블록이 시작될 때 생성
    • 블록이 끝나면 소멸
  • { }내에서만 쓰는 변수
    • scope, 범위가 지정된 변수
    • 선언된 블록(scope)이 끝나면 사라짐 (메모리 해제)
      • 엄연하게는 살아있거나, 없거나
        • 메모리가 내려가, 다른 context block에 덮어씌어질 수 있다
    • scope를 벗어나면 사용 할 수 없다
  •   void f() {
          int x = 10;
      }
      
      // f()가 끝나면 x는 없어짐	

전역 변수

  • 저장 위치
  • 생명주기
    • 프로그램 시작부터 끝까지 살아 있음
    • 모든 함수에서 접근 가능
  • 프로그램 전체에서 쓸 수 있는 변수 (스코프가 전역)
    • 함수, 블럭 밖에서 선언한 변수
    • 한 파일 내에서, 여러 파일간 공유가능
    • 프로그램이 종료될때까지 살아 있다 (메모리 점유)
    • 지역 변수와 전역 변수의 이름이 같으면, 지역 변수가 우선순위
  •     int g = 100;   // global variable
        
        void add() {
      	  g += 10;
        }
        
        int main() {
      	  print("%d", g);  // 100
      	  add();
      	  print("%d", g);  // 110
        }

다른 함수에서 해당 지역 변수를 사용하는 방법

  • call by value
    • 파라미터로 값을 전달하여 사용하는 것
    • 수정하여도, 호출자(caller)의 지역변수에 영향 없음
  • call by address
    • 다른 함수에 caller의 지역변수를 접근가능하게 하는 것이 4 - 포인터
    • caller의 메모리에 있는 지역변수의 주소를 넘겨서, 접근 가능한 것
  • call by reference(cpp - &)
  •     void fn(int a){ // <- fn의 변수 a와, main의 a는 이름만 같을 뿐, 다른 메모리를 가르키는 변수
      	  a += 2; // <- fn의 a 변수를 조작
        } 
       
        int main(){
      	  int a = 2;
      	  
      	  fn(a);
      	  print("%d", a); // <- main의 a 변수를 출력
        }

static 지역 변수

  • 저장 위치
  • 생명주기
    • 프로그램 시작부터 끝까지 살아 있음
    • 해당 함수에서 접근 가능 + 4 - 포인터
  •   void f() {
          static int cnt = 0;
          cnt++;
      }

heap 메모리

  •     int* p = malloc(sizeof(int));
  • 저장 위치
  • 수명
    • free 할 때까지
      • 메모리 관리의 필요성
        • GC
        • cpp RAII
          • 생성자
          • 소멸자
  • 장점
    • 크기와 수명을 유연하게 관리 가능
  • 단점
    • 누수
    • double free
    • use-after-free