함수와 모듈화가 중요한 이유

  • 함수나 모듈화를 활용하지 않고 프로그램을 만들다보면 점점 프로그램의 복잡성이 증가하다가 손도 댈 수 없는 프로그램이 됨
  • 복잡성을 느끼는 이유는 한번에 너무 많은 정보와 문맥을 파악해야 하기 때문
  • 프로그램의 복잡성을 줄이려면 프로그램을 여러 개의 작은 단위로 쪼개야 하는데 그것이 모듈화의 목적이고, 이를 달성시킬 수 있는 기능이 함수

모듈화

  • 모듈(Module)은 쉽게 말하면 파츠
  • 프로그램에서 모듈화라는 것은 전체 프로그램을 여러 파트로 나누는 것
  • 라이브러리도 모듈이라고 할 수 있음 (네임스페이스 하나하나가 모듈)
  • 모듈 하나하나는 논리적 또는 기능적으로 분리되어 독립적인 일을 수행할 수 있어야 함. 잘못된 모듈화는 프로그램의 복잡성을 줄이기는 커녕 되려 증가시킬 수 있음
  • 모듈화를 잘하면 유지보수성이 높아짐
  • 모듈화를 위한 기능으로 함수와 클래스가 있음

    유지보수성 : 추후에 쉽게 확장 가능한지, 추가기능을 쉽게 넣을 수 있는지, 기존의 기능을 쉽게 수정할 수 있는지. 확장성이 높다라고 표현

함수

  • 일련의 과정에 이름을 붙인 것
  • 중복되는 중복코드를 제거해 프로그램의 모듈성을 높일 수 있음

문법

  • 함수는 헤더와 바디로 나뉨
  • 함수는 0개 이상의 매개변수(Parameter)를 가질 수 있음. 즉, 불필요하다면 매개변수를 가지지 않아도 됨
  • 매개변수는 함수의 바디에서 활용되는 변수. 함수의 매개변수는 입력구가 됨
  • 매개변수는 호출연산자() 를 사용할 때 인수(Argument)에 의해 초기화
  • return문을 사용해 호출자에게 결과값을 반환할 수 있음
  • 반환값이 없다면 void 타입 사용
  • 함수는 변수나 상수와는 다르게 제일 밑에다가 정의해도 위에서 동작가능
  • 함수를 많이 쓰게될텐데 위쪽에 몰아 쓰면 실제 구문 실행이 한참 뒤에 나오기 때문에 가독성이 떨어짐. 그래서 앞으로 작성하는 함수들은 되도록 뒤쪽에다가 작성

    매개변수(parameter) = 매개변수도 변수니까 객체

.

가변 인수

  • string타입의 Format함수의 경우 여러 인자를 가질 수 있는데, 이에 값을 대입할 수 있는 기능으로 가변 인수(Variadic Argument)가 있음
  • 가변 인수를 사용하기 위해서는 params라는 키워드 사용
  • 가변 인수는 함수에 넣는 인수의 수가 유동적일 때 유용

스택 프레임

  • 함수는 모든 데이터를 스택 영역에 저장.
  • 스택에 저장된 데이터를 스택 프레임(Stack Frame)이라고 함
  • 스택 프레임은 디버그를 위해서도 사용되는 데, 스택 프레임의 정보를 이용하면 함수가 어떤 순서로 호출되고 있는지 확인할 수 있기 때문. 이를 호출스택 이라고 함
  • 스택 영역은 정적(실행 전) 할당 영역. 즉, 이 함수가 몇 byte의 데이터가 필요한지 프로그램 실행전에 알 수 있음. 컴파일 단계에서 계산함
  • 함수를 호출한 후 필요한 데이터를 전부 할당

    int 타입의 데이터가 3개가 있다면 12byte 이므로 함수를 호출 후 12byte를 할당해주고, 함수를 전부 사용하면 다시 12byte의 데이터를 정리

  • PCB에서 스택 영역을 관리하기 위해 BP(Base Pointer) Register, SP(Stack Pointer) Register를 사용하는데, 이 2개를 가지고 스택의 크기를 구함
  • BP는 스택의 시작, SP는 스택의 끝을 의미

    BP의 주소가 0x1240, SP의 주소가 0x1234이면 BP - SP = 12byte이므로 이 프로세스에서 사용하고 있는 스택의 영역은 12바이트

  • 스택 메모리 할당 → SP값을 뺌
  • 스택 메모리 정리 → SP값을 더함
  • 스택 메모리는 아래쪽으로 증가. 메모리 주소가 감소하는 방향으로 늘어남
  • 프로세스가 사용하는 스택 메모리는 보통 1mb 정적 할당이기 때문에 이 크기는 변하지 않음. 이 스택 메모리 크기는 컴파일러 옵션으로 변경할 수 있지만, 보통 스택 메모리의 크기를 변하게 하는 경우는 없음

빨간 부분이 BP, 파란 부분이 SP라고 가정했을 때 함수를 호출할 때 SP(파란부분)가 아래로 늘어나면서 스택 메모리를 할당해주고 함수가 끝나면서 스택 메모리를 정리할 때 SP가 다시 위로 줄어듦. 스택 메모리는 아래쪽으로 증가. 메모리 주소가 감소하는 방향으로 늘어남. 함수가 계속 반복되는 경우 함수가 계속해서 호출되어 SP가 스택 메모리를 할당해주기 위해 계속해서 아래로 늘어나다가 할당된 크기를 벗어나면 스택오버플로우가 발생

호출 규약

  • 호출 규약(Calling Convention)은 함수가 어떻게 호출자로부터 인수를 받을 것이며, 결과값을 호출자에게 어떻게 돌려줄 것인지 규정해 놓은 것. 즉, 스택 프레임에 어떤 데이터를 저장할 것인지 나타낸 것

마이크로소프트 호출 규약 (MS Calling Convention)

  • 인수 전달은 왼쪽에서 오른쪽으로 차례대로 저장
  • 처음 4번째까지의 인수는 레지스터를 통해 전달하고, 5번째부터는 스택 메모리를 통해서 전달함
  • 스택 메모리에 인수를 전달할 때는 8바이트를 사용
  • 정적 할당 후 레지스터에 저장된 인수를 스택으로 옮김
  • 스택 메모리에 저장되어 있던 인수는 주소 계산으로 가져옴
  • 결과 데이터(반환값)는 EAX 레지스터를 사용해서 가져옴

객체의 속성

범위

  • 범위(Scope)는 객체가 유효한 영역을 말함
  • 지금까지 사용한 객체는 모두 블록(Block) 범위를 가지고 있으며, 이를 지역 변수(Local Variable)라고 함
  • 반대로 어디서든 접근할 수 있는 변수를 전역 변수(Global Variable)라고 함

수명

  • 객체의 수명(Lifetime)은 객체가 유효한 시간
  • 지역 변수는 범위를 벗어나게 되면 바로 수명이 끝남

인수 전달 방식

  • 인수를 전달할 때는 2가지 방식이 있음
  • 객체의 복사본을 전달하거나, 객체에 접근할 수 있는 주소를 전달하는 것
  • 내가 쓴 코드가 원본에 영향을 주는지를 알아야 하기 때문에 이 둘을 명확하게 인지하고 있어야 함

    Pass By Value 혹은 Call By Value (객체의 복사본을 전달)
    Pass By Reference 혹은 Call By Reference (객체에 접근할 수 있는 주소를 전달하는 것)

  • 기본적으로 인수 전달 방식은 복사본을 전달(Pass By Value)하는 것

주소를 전달(Pass By Reference)하고 싶다면 ref를 사용할 수 있음

  • 주소를 전달하되 의도를 명확하게 하기 위해서 in과 out을 사용할 수 있음
  • in : Pass by Reference이되 함수 내부에서 변경 불가능함을 명시적으로 나타냄
  • out : Pass by Reference이되 함수에서 반환값 이외에도 추가 데이터를 반환함을 명시적으로 나타냄
profile
프로그래머 지망생

0개의 댓글