1. 매개변수 사이의 자료전달 방법
1) 값의 의한 자료전달
기본적인 자료전달 방법이며, 실매개변수와 형식매개변수 사이에 값을 전달합니다.
그러나 호출한 함수의 실행이 끝난 다음 전달받은 값을 리턴받지는 못합니다.
예제)
#include <stdio.h>
void swap(int x, int y);
void main() {
int a = 3, b=5;
printf("호출전 a = %d, b= %d\n", a, b); //출력: 호출전 a = 3, b= 5
swap(a,b); // 함수 호출(실 매개변수)
printf("호출후 a = %d, b= %d\n", a, b); //출력: 호출후 a = 5, b= 3
}
void swap(int x, int y){ // 함수정의(형식 매개변수)
int temp;
temp = x;
x = y;
y = temp;
printf("함수내 x = %d, y = %d\n", x, y); // 출력: 함수내 x = 5, y = 3
}
2) 참조에 의한 자료전달
호출함수와 피 호출함수의 매개변수 값을 서로 교환할 수 있는 자료전달 방법입니다.
이 방법은 실제로 값을 전달한다기 보다는 실매개변수의 값이 들어있는 주소값을 전달합니다.
예제)
#include <stdio.h>
void swap(int *x, int *y);
void main() {
int a = 3, b=5;
printf("호출전 a = %d, b= %d\n", a, b); //출력: 호출전 a = 3, b= 5
swap(&a,&b); // 주소값을 전달하기 위해 실 매개변수 앞에 주소연산자 &를 붙임
printf("호출후 a = %d, b= %d\n", a, b); //출력: 호출후 a = 5, b= 3
}
void swap(int *x, int *y){ // 주소값을 전달받기 위해 포인터변수 int *x, int *y를 선언
int temp;
temp = *x;
*x = *y;
*y = temp;
printf("함수내 x = %d, y = %d\n", *x, *y); // 출력: 함수내 x = 5, y = 3
}
위 두가지 자료전달 방법의 차이는 실매개변수의 값이 변화유무입니다.
값에의한 자료전달은 실 매개변수가 변하지 않지만 참조에 의한 자료전달은 실 매개변수가 변할 수 있습니다.
2. 기억 클래스
기억클래스란 변수를 기억공간의 특정영역에 할당하는 방법입니다. 즉, 각 변수의 유효범위와 존속기간이 존재하기 때문에 어떠한 기억클래스를 사용하느냐에 따라 유효범위와 존속기간을 설정할 수 있습니다.
1) 변수의 사용위치에 따라
1] 지역변수
특정범위내에서만 통용되는 변수입니다. 즉 선언된 블록이나 함수내에서만 사용가능하며, 예로는 함수에서 사용되는 매개변수 등입니다.
2] 전역변수
함수밖이나 외부파일에서 선언되어 프로그램 전체에 걸쳐 사용할 수 는 변수입니다. 참고로 전역변수는 초기화를 하지 않으면 자동으로 0으로 초기화 됩니다.
2) 변수의 존속기간에 따라
기억클래스를 이용한 변수 선언방법은 아래와 같습니다.
형식 : 기억클래스 자료형 변수명;
기능 : 기존의 변수선언문에 기억클래스만 기입
선언된 변수에 저장된 자료는 해당 기억영역에 놓이게 됨
사용 예 : auto int a; //자동변수
static int b; // 정적변수
extern int c; //외부변수
register int d; // 레지스터변수
1]자동변수
함수 실행 시 만들어지고 실행이 끝나면 기억공간이 제거됩니다. 예약어 auto를 사용하는데 auto는 생략이 가능합니다.
이 통용범위는 변수가 선언된 블록이나 함수내로 한정됩니다. 즉 지역변수입니다.
그리고 자동변수는 반드시 초기화를 해야합니다.
예제)
#include <stdio.h>
void main() {
int i = 1;
auto int j = 2;
{ //블록1
int i =3; // 자동변수로서 블록1에서만 사용가능
{ //블록2
int i =4; //자동변수로서 블록2에서만 사용가능
printf("블록2의 i=%d\n",i); //출력: 블록2의 i=4
printf("블록2의 j=%d\n",j); //출력: 블록2의 j=2
}
printf("블록1의 i=%d\n",i); //출력: 블록1의 i=3
}
printf("메인함수내의 i=%d\n",i); //출력: 메인함수내의 i=1
}
위 예제에서 변수 i의 값이 계속 바뀌는 것을 확인할 수 있습니다. 그 이유는 선언함수가 다르면 변수 이름이 같아도 서로 다른 변수를 의미하게 되며 작은 범위의 변수를 우선하게 됩니다.
2]정적변수
기억영역이 프로그램이 끝날때까지 유지됩니다. 예약어는 static을 사용하며 전역변수에 해당합니다.
따라서 변수의 값은 프로그램 실행중에는 계속 유지가 되며 초기화를 하지 않았다면 0으로 초기화됩니다.
예제1)
#include <stdio.h>
void main() {
int a = 10;
static int b = 20;
{
int a = 5; //자동변수이기 때문에 이 블록을 벗어나면 다시 10으로 되돌아옴
printf("a = %d, b = %d\n",a,b); //출력: a = 5, b = 20
}
printf("a = %d, b = %d\n",a,b); //출력: a = 10, b = 20
}
예제2)
#include <stdio.h>
test();
void main() {
int i;
i=0;
while(i<3){
test();
i++;
}
//처음 출력: auto = 0, static = 0
//두번째 출력: auto = 0, static = 1
//세번째 출력: auo = 0, static = 2
}
test(){
auto int a = 0;
static int s = 0;
printf("auto = %d, static = %d\n", a, s);
++a;
++s;
}
위에서 자동변수인 a는 값이 계속 0이지만 s는 값이 계속 변하는 이유는 자동변수는 호출할때마다 값이 초기화되지만, 정적변수는 함수를 빠져나가더라도 프로그램이 종료되지않았기 때문에 값을 유지합니다. 즉 처음한번만 초기화합니다.
따라서 s의 값은 계속 변하게 됩니다.
3]외부변수
함수의 외부에서 선언하며 예약어는 extern을 사용합니다. 그리고 전역변수이며 초기화를 하지않았다면 0으로 초기화합니다.
외부 변수의 특징으로는 다른 파일에서 외부변수로 선언된 변수의 값을 참조할 수 있다는 것입니다.
예제)
#include <stdio.h>
int i = 10;
int j = 20;
void main() {
extern int i; // 예약어 생략 가능 -> 왜냐하면 메인함수 앞에 전역변수로 i를 선언했기 때문
extern int k; //외부 변수 선언 -> 예약어 생략불가 -> 변수 k가 메인함수 아래에 있음
int j= 100;
printf("i=%d, j=%d, k=%d\n", i, j, k); //출력: i=10,j=100,k=50
}
int k = 50;
4]레지스터변수
CPU 내의 레지스터에 자료를 저장하고자 할때 사용합니다. 예약어는 register를 사용하며 자동변수와 동일한 속성을 가지고 있습니다.
이 레지스터 변수는 프로그램의 실행속도 증가를 목적으로 사용하며, 주로 반복문에서 카운터 변수로 사용됩니다.
예제)
#include <stdio.h>
void main() {
register int i;
int sum = 0;
for(i = 0; i < 10; ++i) //레지스터 변수를 반복문의 카운터 변수로 사용
sum+=i;
i -=1;
printf("i=%d, sum = %d\n", i, sum); //출력: i=9, sum = 45
}