4. 포인터 - 변수와 함수
1. 변수 구분
변수가 선언되는 위치에 따라 아래처러 구분된다.
- 전역 변수(블록 외부에 선언)
- 지역 변수(블록 내부에 선언)
변수가 만들어지는 메모리 영역의 위치와 용도에 따라 구분된다.
- 자동 변수(auto)
- 정적 변수(static)
- 외부 변수(extern)
- 레지스터 변수(register)
- 동적 변수
2. 자동변수와 메모리
자동 변수는
블록이 시작될 때 { 생성(메모리에 만들어지고)되고
블록이 끝날 때 } 소멸(메모리에서 삭제)한다.
정적 변수는
프로그램이 시작될 때 생성되고
프로그램이 종료될 때 소멸한다.
자동 변수는 변수 자료형 앞에 'auto' 키워드를 붙여 사용하고
정적 변수는 변수 자료형 앞에 'static' 키워드를 붙여 사용한다.
('auto' 키워드는 생략하는 것이 가능하므로 자료형 앞에 어떤 키워드도 없으면 자동 변수이다.)
auto 사용, auto 생략, 자동 변수 예시
#include <stdio.h>
void func(int n1)
{
int n2 = 20; // auto 생략 가능
auto int n3 = 30;
printf("%d %d %d\n", n1, n2, n3);
}
void main ( )
{
int m = 10;
func( m );
}
자료형 앞에 auto 키워드를 앞쪽에 붙여 자동 변수를 선언하지만, 생략할 수도 있다.
자동 변수는 메모리 영역 중 스택이란 곳에 위치하며 선언된 함수 내에서만 사용할 수있다.
함수 내의 자동 변수들은 함수가 호출될 때 생성되고 함수가 반환될 때 소멸한다.
지역 변수와 메모리 예시
#include <stdio.h>
void func3(int n3){
//
printf("%d\n", n3);
}
void func2(int n2){
//
func3(n2);
}
void func1(int n1){
//
func2(n1);
}
int main()
{
int m = 10;
func1(m);
return 0;
}

1. main( ) 실행 → 2. func1( ) 실행 → 3. func2( ) 실행 → 4. func3( ) 실행 →
5. func3( ) 종료 → 6. func2( ) 종료 → 7. func1( ) 종료
main( ) 함수가 시작되면 m 변수가 생성되고
func1() 함수가 시작되면 n1 변수가 생성되고
func2() 함수가 시작되면 n2 변수가 생성되고
func3() 함수가 시작되면 n3 변수가 생성된다.
func3() 함수가 종료되면 n3 변수가 소멸하고
func2() 함수가 종료되면 n2 변수가 소멸하고
func1() 함수가 종료되면 n1 변수가 소멸한다.
마지막으로 main() 함수가 종료되면 m 변수가 소멸한다.
위와 같이 자동 변수는 함수가 시작될 때 만들어지고 함수가 종료될 때 삭제된다는 것을 알 수 있다.
3. 전역 변수와 메모리
#include <stdio.h>
static int sn1 = 0;
void func()
{
int an = 0;
static int sn2 = 0; // 선언 초기화 반복 x
static int sn3 = 0; // 선언 초기화 반복 x
sn3 = 0; // 재할당
printf("%d %d %d %d\n", an++, sn1++, sn2++, sn3++);
}
void main()
{
func();
func();
}

4. 함수와 포인터
문자열이나 배열은 많은 메모리를 차지하므로
함수에 전달하고자 할 때는, 함수 내에 값을 복사하는 것이 아니라 간단하게 시작 주소를 전달하여 값에 접근한다.
함수의 인자로 전달된 주소를 사용해 값을 변경 - 정수
#include <stdio.h>
void func(int *ip)
{
printf("%p %d\n", ip, *ip);
}
void main ( )
{
int n = 10;
func( &n );
}
함수의 인자로 전달된 주소를 사용해 값을 변경 - 실수
#include <stdio.h>
void func(int *ip) // 함수의 매개변수 이름과, 호출하는 쪽의 변수명을 같게 하지 않아야 합니다.
{
printf("%p %d\n", ip, *ip);
}
void main ( )
{
int n = 10;
func( &n );
}
함수의 인자로 전달된 주소를 사용해 값을 변경 - 배열
#include <stdio.h>
void func(char ap[])// void func(char *ap)
{
printf("%p %c\n", ap, *ap);
printf("%p %p %p %p\n", ap+0 , ap+1 , ap+2 , ap+3);
printf("%c %c %c %c\n", *(ap+0),*(ap+1),*(ap+2),*(ap+3));
printf("%c %c %c %c\n", ap[0], ap[1], ap[2], ap[3]);
}
void main ( )
{
char carr[4] = {'A','B','C','D'};
func( carr );
}
// 0x7ffe1bf8fa14 A
// 0x7ffe1bf8fa14 0x7ffe1bf8fa15 0x7ffe1bf8fa16 0x7ffe1bf8fa17
// A B C D
// A B C D
#include <stdio.h>
void func(int *ap) // void func(int ap[])
{
printf("%p %d\n", ap, *ap);
printf("%p %p %p %p %p\n", ap+0, ap+1, ap+2, ap+3, ap+4);
printf("%d %d %d %d %d\n", *(ap+0), *(ap+1), *(ap+2), *(ap+3), *(ap+4));
printf("%d %d %d %d %d\n", ap[0], ap[1], ap[2], ap[3], ap[4]);
}
void main()
{
int iarr[5] = {10, 20, 30, 40, 50};
func(iarr);
}
// 0x7ffcb83e3b20 10
// 0x7ffcb83e3b20 0x7ffcb83e3b24 0x7ffcb83e3b28 0x7ffcb83e3b2c 0x7ffcb83e3b30
// 10 20 30 40 50
// 10 20 30 40 50
함수의 인자로 전달된 주소를 사용해 값을 변경 - 2차원 배열
다음 포스트에 계속..