c 8. 함수와 변수

 c 8. 함수와 변수



1. 함수에서 변수 사용

변수의 사용 범위는 함수 내부에서 선언한 것인지, 외부에서 선언한 것인지에 따라 달라짐 


- 지역 변수와 전역 변수

* 지역 변수

함수 안에서 선언된 변수

해당 함수 또는 지역변수를 선언한 코드 블록 안에서만 사용 가능

선언한 함수 구간이 다르면 동일한 이름으로 선언 가능


* 전역 변수

함수 외부에서 선언된 변수

소스 파일 어느 위치에서도 사용 가능

하나의 프로젝트에 여러 개의 소스 파일이 존재 할 경우 모든 파일에서 사용 가능



- 변수의 속성

변수의 용도를 지역 변수, 또는 전역 변수로 사용할 것인지를 결정하는 것.

변수의 속성을 무시하고 선언하면 컴파일 오류 발생 가능

변수를 어느 위치에 선언하는지에 따라 변수의 사용 범위가 달라짐



- 변수의 생성과 소멸

생성 : 변수를 선언하는 것으로 시작

소멸 : 변수가 속한 함수나 코드 블록이 끝나는 마지막 구간에서 종료

변수의 생존 시간 : 변수가 생성되고 소멸하는 주기


변수를 생성하면 메모리에 자료형의 크기만큼 공간이 확보되었다가 변수의 생존 시간이 다할 때까지 유지 



- 변수의 연결

여러 소스 코드에서 전역 변수에 공동으로 접근하여 사용 가능

내부 연결과 외부 연결이 있음

지역 변수는 연결이 불가능하고 전역 변수만 연결 가능







2. 지역 변수


- 지역 변수의 선언

특정 지역 내에서만 선언하여 사용

선언된 코드 블록을 벗어나면 사용할 수 없음













* 예시 - 지역 변수를 코드 블록에서 벗어나서 사용하려고 하는 경우

#include <stdio.h>

int main(void) {

int cnt;

printf("1부터 10까지 누적 합계 출력\n");

for (cnt = 1; cnt <= 10; cnt++) {
int sum = 0;
sum += cnt;
}

printf("1부터 10까지 누적합계 : %d\n", sum);
return 0;
}

- 지역변수를 코드 블록 밖에서 사용하려고 했기때문에 선언한 적 없는 식별자라는 에러 발생


코드 수정 =>

#include <stdio.h>

int main(void) {

int cnt;
int sum = 0;

printf("1부터 10까지 누적 합계 출력\n");

for (cnt = 1; cnt <= 10; cnt++) {
sum += cnt;
}

printf("1부터 10까지 누적합계 : %d\n", sum);
return 0;
}








- 지역 변수의 생성과 소멸

생성되면 스택(stack)이라는 메모리 공간에 자동으로 생성

선언된 코드 블록이 끝나면 메모리 공간을 반환하고 소멸

소멸되면 프로그램을 다시 실행해야만 사용할 수 있음



* 지역 변수 초기화

반드시 초기화 값을 수행해야 함

초기화를 하지 않고 선언하면 변수에 임의의 값이 대입 되어 오류 발생


반복문 안에서 지역 변수를 선언하여 사용하는 경우 반복문이 실행될 때마다 변수가 초기화 되므로 누적 합계 등을 구할 때는 논리 오류가 발생 -> 반복문 밖에서 변수를 선언하고 초기화해서 사용해야 함



- 지역 변수 사용 시 주의사항


* 지역 변수와 매개 변수

매개 변수도 함수 안에서 지역 변수처럼 사용됨

매개 변수는 함수를 호출할 때마다 인수의 값으로 초기화 됨

함수 안에서는 지역 변수보다 매개 변수를 사용하는 것이 더 효율적



* 동일한 지역 변수 사용

동일한 이름의 변수를 다른 코드 블록 안에서 선언해서 사용해도 오류가 발생하지 않음

컴파일러에서 메모리 주소로 찾아가기 때문에 서로 다른 변수로 인식







3. 전역 변수


- 전역 변수의 선언

함수 외부에서 선언되어 소스 파일 전체에서 사용 가능

특정 블록 구간 내에서만 사용되지 않고 다른 함수들과 공동으로 사용

main()함수나 사용자 정의 함수에서도 접근 하여 사용 가능













- 전역 변수의 생성과 소멸

프로그램 시작과 동시에 생성되어 프로그램이 종료될 때까지 메모리 공간 사용

선언과 동시에 컴파일러가 자동으로 0으로 초기화

사용자 정의 함수에서 매개 변수가 아닌 전역 변수를 사용할 수도 있음 -> 인수 없이 호출


* 예시 - 전역 변수를 사용하여 인수 없이 호출되는 사용자 정의 함수

#include <stdio.h>

int add();
int a;
int b;

int main(void) {

a = 10;
b = 20;
int sum = 0;
printf("10 + 20 계산\n");

sum = add();

printf("10 + 20 = %d\n", sum);
return 0;
}
int add() {
int sum = 0;
sum = a + b;
return sum;
}








- 전역 변수의 이름과 지역 변수의 이름이 겹치는 경우

지역 변수가 우선시 되어 지역 변수가 전역 변수를 가림


* 예시 - 지역 변수와 전역 변수가 같은 이름으로 선언되어 사용되는 경우

#include <stdio.h>

int a = 1;

int main(void) {

int a = 10;

printf("전역 변수 a = 1, 지역 변수 a = 10\n");
printf("a = %d\n", a);

return 0;
}










4. 동적 변수와 정적 변수


- 동적 변수(자동 변수)

코드 블록의 마지막 구간에서 소멸되는 변수

키워드 'auto'를 붙여서 선언하나 생략해도 자동으로  동적 변수로 선언됨


'int a;' 와 'auto int a;' 는 같음



- 정적 변수

프로그램이 실행될 때 메모리에 생성되고 프로그램이 종료되면 메모리 공간을 비움

변수가 선언된 함수나 코드 블록을 벗어나서도 사용할 수 있음

변수가 선언된 범위를 벗어나도 자동으로 삭제되지 않음

개념적으로 전역 변수와 같으며 전역 변수처럼 사용할 수 있음

다른 소스 코드에서 불러서 사용할 수 없음


키워드 'static'을 붙여서 선언

선언할 때 초기화 하지 않으면 컴파일러가 자동으로 0으로 초기화

한 번 초기화된 정적 변수는 다시 초기화할 수 없음



* 예시 - 동적 변수와 정적 변수의 차이

#include <stdio.h>

void count(); // 사용자 정의 함수 선언

int main(void) {

printf("count() 함수 3회 호출 결과\n");
count();
count();
count();

return 0;
}
void count() {

static int s_cnt = 0; // 정적 변수 선언, 초기화
int a_cnt = 0; // 동적 변수 선언, 초기화

printf("정적 변수 = %d, 동적 변수 = %d\n", s_cnt, a_cnt);
s_cnt++;
a_cnt++;
}







프로그램이 실행되고 종료될 때마다 동적 변수는 소멸되고 다시 생성되어 초기화 되지만, 정적 변수는 소멸되지 않고 처음 초기화된 이후로도 다시 초기화 되지 않음.







5. 변수의 연결

다른 함수나 코드 블록에서 생성된 변수를 서로 연결하는 기능


- 변수의 외부 연결

지역 변수는 연결할 수 없고 전역 변수만 연결할 수 있음

'extern' 키워드를 사용해서 선언

하나의 프로젝트에 여러 소스 파일이 있는 경우 하나의 전역변수를 선언한 뒤 프로젝트에 존재하는 여러 소스 코드에서 'extern' 키워드로 선언하면 해당 전역 변수에 접근 가능








* 프로그램 내에 소스 코드가 여러개인 경우 mian()함수는 반드시 하나여야만 함.




- 변수의 내부 연결

소스 코드 안에서만 변수를 사용할 수 있도록 연결

전역 변수 앞에  'static' 키워드를 선언

'stiatic' 키워드로 선언된 변수는 다른 소스코드에서 참조할 수 없음

변수의 참조 가능 여부는 'static' 키워드에 달려있음













- 참조와 연결

c언어 프로젝트 안에 main.c파일과 func.c 파일 생성

각각 코드 작성(이때 main()함수는 한 번만 사용 되어야 함)


main.c

#include <stdio.h>


int A;          // 정적 변수 선언

static int B;   // 정적 전역 변수 선언


void inFunc(void); // 정적 전역 변수 사용한 사용자 정의 함수 선언

extern void outFunc(void); // 외부 파일 사용자 정의 함수 선언


int main(void) {


    printf("전역 변수로 외부 연결 함수 호출\n");

    printf("키워드 사용 : extern\n");


    outFunc(); // 외부 함수 호출


    printf("1. 외부 연결 함수에서 값 출력 : %d\n", A);


    printf("정적 지역 변수로 내부 연결 함수 호출\n");

    printf("키워드 사용 : static\n");


    inFunc(); // 내부 함수 호출

    printf("2. 외부 연결 함수에서 값 출력 : %d\n", B);


    return 0;

}

void inFunc() { //  정적 전역 변수 사용한 사용자 정의 함수 정의


    B = 20;

    printf("\n내부 inFunc() 함수 영역\n");

}



func.c

#include <stdio.h>


extern int A;


void outFunc(void)

{

    A = 10;

    printf("\n외부 함수 outFunc() 영역\n");

}











inFunc() 함수는 같은 소스 코드 안에 있는 정적 전역 변수 B를 연결해서 초기화 했고 func.c 파일에 있는 outFunc() 함수는 전역변수 A를   'extern int A;' 로 불러와서 연결해서 초기화




- static 함수 정의

함수의 이름 앞에도 'static' 키워드를 선언할 수 있음

함수를 동일한 소스 코드 안에서만 사용하겠다는 의미


* 위의 예제에서 외부 함수의 이름 앞에 'static' 키워드를 선언했다면 main.c 파일에서 불러올 수 없음





- 변수의 타입 지정자

지역 변수와 전역 변수는 변수의 선언 위치에 따라 결정

일반 변수를 특정한 범위 내에서만 사용하거나 외부 파일에서 참조할 수 있도록 선언하려면 변수에 대한 타입 지정자를 사용

* 변수 타입 지정자 종류










* 레지스터 변수

CPU 내에 있는 레지스터 저자공간을 사용하는 변수

프로그램의 실행 속도를 빠르게 함

지역 변수만 사용할 수 있음

'register' 키워드를 사용

사용을 권장하지는 않음










댓글

이 블로그의 인기 게시물

Spring Boot 6. 계시판 프로젝트

Spring Boot 2. Maria 데이터베이스 & Spring Data JPA

Django 10. DB 연동