본문 바로가기
TIL/따배씨

함수 (2021-01-13 ~ 2021-01-14)

by Dev_Dank 2021. 1. 13.

9.1 함수가 필요할 때

문자열을 출력하는 방법을 기억하지 못해 문자열 입출력을 잘못했다.
한번 더 lemonade-my-neck-was-drippin.tistory.com/6

 

문자열과 형식 맞춘 입출력 (2021-01-05)

4.1 문자열 출력하기 "char 변수명" -> 글자 1개만 저장가능 뒤에 대괄호[]를 써서 저장공간을 더 확보 가능 (실제 변수자체가 더 큰 용량을 갖는 변수자체가 되는 것 아니라 추가로 지정한 크기만큼

lemonade-my-neck-was-drippin.tistory.com

9.2 함수의 프로토타입

컴파일과 링킹이 분리되어있다는 점에 주의 

함수의 프로토타입만 선언해도  컴파일은 가능하지만 링킹(실제로 실행 파일을 만드는과정)에서 문제가 발생한다. 

F7을 눌러서 빌드를 해보면 위의 프로그램은 컴파일에러는 발생하지 않고 링킹에러가 발생한다. 

Visual studio에서는  함수의 프로토타입을 바로 분리 할 수 있음.

함수 우 클릭 -> Quick Actions and..... 클릭
Create Declaration / Definition 클릭

프로토 타입 부분에서는 변수명을 안쓰고 자료형만 지정해줘도 괜찮다. 
(하지만 실무에서는 다 입력해주는게 보기 쉬움)

프로토타입에 변수명이 없는 경우

9.3 함수의 자료형과 반환값

함수에서 반환자료형이 int인 경우 생략이 가능하다. 
(어차피 실무에서는 다 표시하는게 좋음)

반환값이 없이 함수가 끝날수도 있다. 

9.4 변수의 영역과 지역 변수

변수가 유효한 범위는 해당 함수의 영역 {} 안에서만 사용가능
같은 공간의 더작은 범위내에서는 사용가능

int a 를 main함수((int_max(1, 2); 하는 부분)와 main함수내의 영역(int_max(4, 5); 하는 부분)에서 사용하고 있음.

 

특정 영역{} 내에서 선언되어 해당 지역에서만 사용가능한 변수는 지역변수라함

아예 영역 바깥에서 선언된 변수는 파일 전역에서 사용가능

int a 는 파일 전체에서 사용가능한 변수다. 

변수는 메모리의 공간이며 그리고 메모리는 주소를 통해 접근한다


printf("%p\n", &a);를 사용하면 메모리의 주소를 출력할 수 있으며 해당기능을 통해 변수가 서로 다른건지 같은건지 확인이 가능하다. 
(%p 는 포인터를 의미하며 &는 scanf때와 마찬가지로 변수의 메모리 주소를 나타내기 위해 쓰는 것)

 

int a 변수의 주소값은 계속 동일하게 출력된다.

큰영역 안에 작은 영역을 만들고 같은이름의 변수를 선언하면 해당 변수는 다른 변수다. 

작은영역내에서 선언된 int a는 주소가 다르게 출력된다. = 다른 변수이다.

작은 영역에서 선언한 변수는 바깥에서는 사용이 안된다. 

int b 를 작은 영역에서 선언 후 밖에서 사용하려고 하면 빨간줄이 뜨며 에러발생....

9.5 지역 변수와 스택

글자로 설명하기가 어려운 강의이다. 내 스스로 위의 사진을 보고 설명이 가능하므로 별도의 정리 없이 넘어 가도록 하겠다.

9.6 재귀 호출

디버거 f11을 이용하면 재귀함수가 호출되는 과정을 살펴볼수 있다.

9.7 재귀 호출과 스택

int는 4바이트였다. 그런데 위의 예제의 실행결과를보면 n의 숫자차이가 4이상이다.

실제로는 컴퓨터가 프로그램을 실행할떄는 메모리에 프로그램을 올려서 사용한다. 따라서 n 뿐만 아니라 함수 자체도 스택에 올라가서 숫자 차이가 더 큰것.

9.11 헤더 파일 만드는 방법

함수가 한두개 정도면 main 파일에서 한번에 같이 작성해서 사용하면 괜찮지만 그이상으로 가면 헤더 파일을 따로 만들어 따로 관리 하는 것이 편하다. 

헤더파일에 쓸 함수를 만들어 놓고
main 파일에서 그것을 include 시켜서 사용 가능.

 

위의 예제에서 main 함수에 #include <stdio.h>가 없는데 오류가 발생하지 않는것은 헤더파일에서 이미 #include <stdio.h> 작성 했기 때문이다. (즉 헤더파일에서 포함되어있으면 메인 함수에 없어도 사용가능) 

아래의 예시처럼 C파일을 추가로 만드는 방법도 있다.
(헤더 파일의 함수내용을 c 파일로 만들어 함수의 내용은 c파일로 따로 관리.)

헤더 파일에는 함수의 프로토 타입만 남겨 놓고.

 

함수의 내용은 동일한 c파일을 만들어 거기에 작성해서 관리.

9.12 포인터의 작동 원리

포인터는 주소값을 저장하는 변수이다. 

포인터는 일반적인 변수가 작동하는것처럼 저장되어있는 데이터에 바로 접근하는 것이 아니라. 메모리 주소값을 참조하여 값을 활용한다. 

&는 주소연산자로 특정값이 사용하고 있는 메모리 주소를 가져온다. 주소값을 저장하는 변수는 선언할때*을 앞에다가 붙여주면 된다. 

변수 a가 int였으므로 a변수의 주소를 저장할 *a_ptr도 int 자료형으로 선언해야하는 점에 주의 
포인터 변수를 이용하는것을 간접 접근(indirection) / 역참조 (dereferencing) / 방향 재지정(redirection) 같은 용어로 부른다. 
*a_ptr을 활용하려하면 메모리주소로가서 참조하고 있는 값을 가져온다.

9.13 포인터의 기본적인 사용 방법

포인터 변수 선언시 변수명 앞(int *a_ptr) 또는 자료형(int* a_ptr) 뒤에 *를 붙일수 있음(코딩 스타일에 따라 다름)

포인터에 저장된 주소를 출력하는 형식 지정자는 %p이다.

포인터 변수선언후 *(dereference operator)를 붙여서 사용하면 포인터에 저장된주소로 타고들어가 값을 가져오거나 덮어쓰거나 함. *를 안붙이고 사용하면 포인터 변수에 저장된 메모리 주소만 출력이 됨. 

b = *a_ptr; 을 한후 나중에 *a_ptr = 789;로 a의 값을 바꿔도 b의 값은 바뀌지 않고있다. 
b는 그저 int로 선언된 일반 변수고 b = *a_ptr;  이후 *a_ptr에서 무슨 짓을하던a와 관계가 없기 때문이다.

9.14 포인터와 코딩 스타일

이하의 2개의 경우 a만 포인터 변수로 선언되고 b는 그냥 int 자료형 변수로 선언됨

두개다 포인터로 선언하고 싶으면 이하의 두가지 경우 처럼 해야한다. 

혼란을 막고 싶다면 그냥 아래처럼 따로따로 선언하는게 좋다. 

9.15 NULL 포인터와 런타임 에러

포인터는 초기화를 해주지 않으면 쓰레기 값이 들어있는 상태로 남아있어서 런타임 에러를 발생시킬수 있다. 그래서 포인터 변수를 선언할때 NULL 값으로 초기화 하여 안전하게 사용하는 편이다.

9.17 포인터 변수의 크기

포인터변수는 메모리 주소의 값을 저장하는 것이기 때문에 자료형이 달라져도 크기가 같다. 

다만 프로그램이 구동되는 시스템에 따라 달라짐

64비트 운영체재에서는 8바이트

 

32비트에서는 4바이트

9.18 포인터형 매개변수

함수의 매개변수로 포인터를 받을때는 인자를 넣을 때 &붙여서 입력해줘야함. 

댓글