본문 바로가기

Programming

[C언어] C언어 기초강좌 7 / C언어 / 프로그래밍 기초 / 프로그램 만들기

이번 강좌에서는 C언어에서의 함수의 사용법에 대해서 알아보도록 하겠습니다.

1. 함수에 값 전달. 



여러분이 어떤 함수를 만든다고 합시다. 

그 함수는 printf와 같이 어떤 내용을 화면에 출력하는 함수이죠. 

그런데 화면에 무언가를 출력하기 위해선 그 출력할 내용을 
전달받아야 겠죠? 어떻게 하면 전달받을수 있을까요? 

바로 그 방법에 대해서 자세히 알아보도록 하죠. 

저번 2회때 함수에 대해 배울때 인수라는 것이 있었습니다. 

그때 인수는 함수가 어떤 처리를 할때 필요해서 전달받을 데이터라고 

했죠. 이 인수를 통해서 함수가 값을 전달받을수 있습니다. 


(1) 인수가 정확히? 

인수에 대해 정확히 말하자면 함수에서 값을 전달받는데 쓰이는 

변수를 말합니다. 즉 변수의 일종이죠. 아니 일종이 아니고 

변수라고 생각하세요. 단 함수 시작시에 전달받을 값이 들어가게 됨니다. 


(2) 인수 만들기. 

인수는 어떻게 만들까요? 저번 2회때 함수 만드는 방법에 나와 있던것처럼 

함수이름 옆에 있는 ()안에 인수를 나열해 주면 됨니다. 

()안에 마치 변수를 선언하듯이 인수를 만들어 주면 되죠. 

(인수가 변수니까 당연한 거죠?) 

예를 들어 아무 값도 리턴하지 않고, 인수는 정수형태 a와,b를 가진 

func라는 함수는 


void func(int a, int b) 

{ 

. 

. 

. 

} 


이런식으로 만들수 있겠죠? 


(3) 인수의 사용 

이제 인수가 변수라는건 알고 계시죠? 그러므로 인수 사용은 

변수와 똑같다는 것도 아시겠죠? 뭐 더이상 설명드릴 것두 없군요. 

그럼 중요한것 한가지 말씀드리죠. 

우선 예제를 보세요. 


/* 파일 이름 : C8-3.C 

프로그램 내용 : 함수 예제 */ 

#include 

void func(int data) 

{ 

data=10; 

} 

void main() 

{ 

int var=1; 

func(var); 

printf("%d\n",var); 

} 


이 예제를 잘 보세요. 

여기서 main함수에는 var이란 변수가 있죠? 

그리고 그 변수에 초기값으로 1을 주었죠. 

그런다음 func를 호출했는데, 인수로 var이란 변수를 주었죠? 

그럼 func함수를 보세요. func함수에는 data라는 인수가 있는데 

이 함수 호출시에 var이란 변수에는 1이 들어있었으므로 

data에도 1이 들어갑니다. func에서는 data를 10으로 바꾸고 있군요. 

그럼 이렇게 data를 10으로 바꿨는데, main함수의 var이란 변수도 

10으로 바뀔까요? 이 프로그램을 실행해 보시면 아시겠지만 

바뀌지 않습니다. 함수 호출시에 변수를 인수로 주면 단지 

변수에 들어있는 값을 복사해서 전달해 줄 뿐이죠. 

그러므로 바뀌지 않습니다. 이렇게 함수에 값 전달시 

변수에 들어있는 값을 그냥 복사해서 전달해 주는 호출 방법을 

Passing by value라고 합니다. 




2. 배열 



배열은 저번에 문자열을 배울때 문자배열 때문에 간략히 

설명 드린 적이 있습니다. 

이번엔 그 배열에 대해 좀더 자세히 배워보도록 하겠습니다. 

배열이란 데이터 구조의 하나로 데이터들을 일정 수 만큼 

늘어놓은 구조라고 생각하시면 됨니다. 이때 각각의 데이터를 

배열의 원소라고 합니다. 

배열은 많은 데이터를 관리할때 편하죠. 


(1) 배열의 선언 

배열은 변수와 마찬가지로 사용전에 선언해야 합니다. 

선언은 다음과 같이 합니다. 


데이터형태 배열명[배열크기]; 


이렇게 하죠. 

여기서 데이터 형태는 배열에 저장할 데이터에 형태이고, 

배열명은 그 배열을 상징하는 심볼, 배열 크기는 몇개의 데이터를 

늘어놓을 것 인지를 정하는 것 입니다. 

예를 들어 정수 형태의 데이터를 10개 늘어놓은 Array라는 배열은 


int Array[10]; 


이렇게 선언합니다. 


(2) 배열의 사용 

배열을 선언했으면 사용법도 알아야 겠죠? 배열 사용은 


배열명[첨자] = 값; 

변수 = 배열명[첨자]; 


이런 식으로 사용합니다. 

여기서 첨자는 배열의 늘어놓은 데이터중 몇번째 원소를 사용할 건인지를 

정하는 것 입니다. 그리고 첨자의 시작은 0부터라는 것을 기억하세요. 

예를 들어 아까 Array라는 배열의 첫번째 원소에 10을 넣을때는 


Array[0]=10; 


이렇게 하는 것이죠. (첨자의 시작이 0이므로 첫번째 원소의 첨자는 0) 


(3) 배열의 초기값 

보통 변수들은 선언할때 초기값을 줄수 있습니다. 

그런데 배열에 초기값을 줄순 없을까요? 

당연히 할수 있죠..! 

그런데 일반 변수의 초기값을 주는 것보다 좀 복잡합니다. 

배열의 초기값을 주는 방법은 


데이터형태 배열명[배열크기] 

= { 1번째 원소의 초기값, 2번째 원소의 초기값, ... }; 


이렇게 하면 됨니다. 

즉 {}안에 각 원소의 순서대로 초기 값을 적어주면 되는 것이죠. 

예를 들어 아까 Array배열에 1부터 10까지의 초기값을 넣어 선언하면 


int Array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 


이렇게 됨니다. 이렇게 하면 Array[0]에는 1이, Array[1]에는 2가... 

Array[9]에는 10이. 이런식으로 들어갑니다. 

배열을 초기값을 주어서 선언할때는 배열크기를 생략해도 됨니다. 

즉 위에것은 


int Array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 


이렇게만 해 줘도 된다는 것이죠. 

이렇게 해 주면 초기값이 10개이므로 자동으로 배열크기를 10으로 지정해 줌니다. 

하지만 초기값이 없을땐 반드시 크기를 지정해야 합니다. 

즉 


int Array[]; 


이렇게 선언하는 건 절데로 안됨니다. 

배열의 초기값을 주는건 일부만 주어도 됨니다. 

즉 배열의 원소수가 10개이어도 앞에 5개만 초기값을 주어도 된다는 것이죠. 

예를 들어 


int Array[10] = { 1, 2, 3, 4, 5 }; 


이렇게 하면 앞에 5개의 원소만 초기값이 들어가고 

나머지는 초기값이 없게 됨니다. 

만약 배열이 문자 배열일때는 문자열 그대로를 초기값으로 주어도 됨니다. 

즉 


char Array[10] = "String"; 


이렇게해도 된다는 것이죠. 

이렇게 선언한것과 


chat Array[10] = { 'S', 't', 'r', 'i', 'n', 'g' }; 


이렇게 선언한것의 차이는 무엇인지 아시겠죠? 

처음 방법으로 선언한건 문자열을 그대로를 초기값으로 주었으므로 

끝에 NULL문자가 들어가겠죠? 그러므로 


chat Array[10] = { 'S', 't', 'r', 'i', 'n', 'g', NULL }; 


이것과 똑같은 것이 됨니다. 




6. 다차원 배열 



위에서 배운 형태의 배열을 1차원 배열 이라고 합니다. 

하지만 배열에는 2차원 배열 3차원 배열등등 계속 이어지죠. 

이렇게 2차원 배열 이상을 통틀어 다차원 배열 이라고 합니다. 

사실 다차원 배열이라고 해서 1차원 배열과 크게 다를것이 없습니다. 

C에서 다차원 배열은 쉽게 배열의 배열.. 이라고 생각하시면 됨니다. 

예를 들어 2차원 배열은 배열의 배열이고, 3차원 배열은 배열의 배열의 배열이 

되는 것이죠. 


(1) 다차원 배열의 선언 

1차원 배열은 선언할때 일반 변수 선언과 똑같으나 []를 붙여주고 

그 안에 배열의 크기만 정해주면 되었었죠? 

2차원 배열은 배열의 배열이니 선언은 1차원 배열과 똑같으나 

[]를 더 붙여주고 그 안에 배열 크기를 넣어주면 되는 것이죠. 

즉 


데이터형태 배열명[배열크기][배열크기]; 


이렇게 선언해 주면 되는 것 입니다. 

3차원 배열 역시 2차원 배열 선언과 똑같으나 []를 더 붙여주고 

그 안에 배열 크기를 넣어 주면 됨니다. 그러니까 


데이터형태 배열명[배열크기][배열크기][배열크기]; 


이렇게 선언해 주면 3차원 배열이 되는 것 입니다. 

4차원 5차원...도 이런 식으로 []만 늘어날 뿐이죠. 

예를 들어 Array라는 10*10의 크기를 갖는 2차원 정수 배열은 


int Array[10][10]; 


이렇게 선언하면 됨니다. 

만약 10*10*10의 크기를 갖는 3차원 배열이라면 


int Array[10][10][10]; 


이렇게 선언하면 되겠죠? 


(2) 다차원 배열의 사용 

다차원 배열 사용시에도 단지 []만 늘어나게 됨니다. 

2차원 배열의 경우 


배열명[첨자][첨자] = 값; 

변수 = 배열명[첨자][첨자]; 


이렇게 사용할수 있고, 3차원 배열의 경우는 


배열명[첨자][첨자][첨자] = 값; 

변수 = 배열명[첨자][첨자][첨자]; 


이런 식으로 사용할수 있죠. 

예를 들어 보죠. 아까 예로 들었던 Array라는 10*10크기의 

2차원 정수 배열이 있을때, 1번째 배열의 3번째 원소에 3을 넣으려면 


Array[0][2]=3; 


이렇게 해 주면 됨니다. 

만약 Array라는 10*10*10크기의 3차원 정수 배열이 있다고 하고, 

1번째 배열의 3번째 배열의 2번째 원소에 2를 넣으려면 


Array[0][2][1]=2; 


이렇게 하면 됨니다. 


(3) 다차원 배열의 초기값. 

다차원 배열 역시 초기값을 가질수 있습니다. 

다차원 배열에 초기값을 넣는것 역시 다차원 배열이 배열의 배열이라는 것을 

생각하시면 쉽게 하실수 있습니다. 

1차원 배열에 초기값을 지정할때는 {}안에 초기값을 원소의 순서데로 

써 주면 되었었죠? 

그러므로 2차원 배열은 배열의 배열 이므로 {}안에 

또 {}를 써서 초기값을 주면 됨니다. 예를 들어 


int Array[2][3]; 


이런 배열이 있다고 합니다. 이걸 초기값을 주어서 선언하면 


int Array[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; 


이렇게 하면 되는 것이죠. 

3차원 배열 이라면 {}안에 {}안에 또다시 {}안에 원소의 초기값을 

써 주면 되는 것이고요. 즉 


int Array[2][3][2] = { { { 1, 2 } , { 3, 4 }, { 5, 6 } }, 

{ { 7, 8 } , { 9, 10 }, { 11, 12 } } }; 


이렇게 하면 됨니다. 

다차원 배열에 초기값을 지정하는 방법은 이것 말고도 

그냥 1차원 배열처럼 지정하는 방법도 있습니다. 

1차원 배열처럼 {}안에 배열의 모든 원소의 순서대로 초기값을 적어 주는 것이죠. 

예를 들어 아까 


int Array[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; 


이건 


int Array[2][3] = { 1, 2, 3, 4, 5, 6 }; 


이렇게 써 주어도 상관 없습니다.




7. 배열을 인수로 전달.



아까 함수에 값 전달하는 방법을 배웠죠? 

그런데 그때 배운건 일반 데이터에 대한 것이었습니다. 

그럼 배열을 인수로 전달한다면 어떻게 할까요? 

배열 역시 일반 데이터와 전달 방법이 똑같습니다. 

그냥 인수를 배열로 만들어 주면 되죠. 

예를 들어 아무 값도 리턴하지 않고, 인수로는 

정수형태의 10개의 원소를 가진 a라는 배열이 있는 func라는 함수는 


void func(int a[10]) 

{ 

. 

. 

. 

} 


이렇게 만들고 인수 사용도 일반 배열과 똑같이 사용하면 됨니다. 

그런데 여기서 배열의 크기를 생략해도 됨니다. 

즉 


void func(int a[]) 

{ 

. 

. 

. 

} 


이렇게 해도 된다는 거죠. 이렇게 해도 아무 상관 없어요. 

두가지의 차이점은 전혀 없죠. 

그럼 여기서 중요한것 한가지를 말씀드릴께요. 

예제를 보시죠. 


/* 파일 이름 : C8-4.C 

프로그램 내용 : 함수 예제 */ 

#include 

void func(int data[]) 

{ 

data[0]=10; 

} 

void main() 

{ 

int i; 

int var[10]={ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; 


func(var); 

for(i=0;i<10;i++) 

printf("%d\n",var); 

} 


이 소스는 아까 나왔던 예제를 조금 변형 시켜서 func함수의 인수를 

배열로 한 것인데요. 

여기서 func함수를 호출할때 var이란 변수를 인수로 주었습니다. 

그리고 func함수에서는 data라는 인수로 배열을 전달받았는데, 

data의 첫번째 원소를 10으로 바꾸고 있죠. 

그럼 이때 main함수에 있는 var이란 배열의 첫번째 원소도 

10으로 바뀔까요? 

아까의 경우를 생각해 보면 바뀌지 않을것 같지만, 바뀜니다. 

이유는 배열을 인수로 전달할 때는 그 주소를 전달해 주기 때문이죠. 

자세한 이유는 지금 설명하기에는 무리이고, 포인터 강좌가 끝난 후에 

설명해 드리죠. 지금은 그냥 바뀐다는 것만 꼭 알아두세요. 

그리고 이렇게 인수 전달시 주소를 전달해 주어 함수에서 인수의 

값을 바꾸면 함수를 호출한 곳의 변수도 값이 바뀌는 호출 방법을 

Passing by reference라고 합니다. 


이것으로 이번 강좌를 마치도록 하겠습니다.