함수 (2)
Chan-Su Shin
변수의 유효범위
int main(void) {
int a = 2;
printf(“ %d \n”, a);
{
int a = 5;
printf(“ %d \n”, a);
}
a = a + 1;
printf(“ %d \n”, a);
}
블록 (복합문)
블록
(블록의 중첩)
변수의 유효범위 (2)
• 각 블록은 자신의 블록 안에서 선언된 변수의 사용권을 가진다.
• 각 블록은 자신의 블록 안에서 선언된 변수의 목록을 가진다.
• 하나의 블록 안에 여러 개의 블록이 올 수도 있다. (블록의 중첩)
• 예제:
– 블록 B1은 블록 B2와 B3를 포함하고 있다
(블록들이 중첩된 경우)
– 블록 B2와 B3는 서로가 서로를 포함하고 있지 않다. (블록들이 병렬로 놓인 경우)
{
int a, b;
………
{
float b;
……….
}
……….
{
float a;
………..
}
…………
}
병렬 블록
중첩된 블록
B1
B3 B2
변수의 유효범위 (3)
• 변수는 기본적으로 자신이 선언된 블록 안에서만 유효하다.
• B1의 정수 변수 a, b는 B1 안에서만 유효하다.
(단, B1에 중첩된 다른 블록 안에서는 유효하지 않다. 왜? )
• 그러나 B1의 정수 변수 c는 B2와 B3 내부에서도 유효하다.
(왜? B2, B3 내부에서 정의된 c라는 변수가 없기 때문에)
• B2의 float b와 B3의 float a는 각각 B2와 B3 안에서만 유효하다.
{
int a, b, c;
………
{
float b;
……….
}
……….
{
float a;
………..
}
…………
}
병렬 블록
중첩된 블록
B1
B3 B2
예제 (1)
{ int a = 2, b = 4;
printf(“ %d, %d\n”, a, b);
{
float b = 3.14;
printf(“ %d \n”, a);
b = b + 1;
}
printf(“ %d, %d\n”, a, b);
{
float a = 0.9;
printf(“ %d \n”, b);
a = a * 2;
}
printf(“ %d, %d\n”, a, b);
}
{ int a = 2, b = 4;
printf(“ %d, %d\n”, a, b);
{
int b = 3;
printf(“ %d \n”, a);
a = a + 1;
}
printf(“ %d, %d\n”, a, b);
{
int a = 1;
printf(“ %d \n”, b);
b = b * 2;
}
printf(“ %d, %d\n”, a, b);
}
예제 (2)
{ int a = 1, b = 2, c = 3;
printf(“ %d, %d, %d\n”, a, b, c);
{ int b = 4;
int c = 5.0;
printf(“ %d, %d, %d \n”, a, b, c);
a = b;
{
int c;
c = b;
printf(“ %d, %d, %d \n”, a, b, c);
}
printf(“%d, %d, %d \n”, a, b, c);
}
printf(“%d, %d, %d \n”, a, b, c);
}
예제 (3)
{
int k;
for ( k = 1; k <= 10; k++) { int sum = 0;
sum = sum + k;
printf(“ sum = %d \n”, sum);
}
printf(“ sum = %d \n”, sum);
}
이것 역시 블록이다.
예제 (4)
{
int k, a = 0;
for ( k = -10; k <= 10; k++) {
a = a + absolute(k);
printf(“ a = %d \n”, a);
} }
int absolute (int k) {
int a;
if ( k < 0 ) a = -k;
else
a = k;
return (a);
}
변수의 유효범위의 종류
•
변수는 기본적으로 자신이 선언된 블록 안에서만 유효 하다. (* auto 변수 *)
•
만약, 자신이 선언된 블록 이외의 곳에서도 유효하고 싶다면?
• C에서는 네 종류의 유효범위를 제공한다.
•
네 가지 기억 영역 클래스
– auto – static – extern – register
{
int a, b;
………
{
float b;
……….
}
……….
{
float a;
………..
}
…………
}
B1
B3 B2
auto 변수
•
블록 (또는 함수 본체) 내부에서 기억영역 클래스를 지정하지 않은 채 선언된 모든 변수는 무조건 auto 변수로 간주된다.
•
auto 변수는 선언된 블록 내부에서만 유효하고 해당 블록의 외부에서는 유효하지 않다.
•
블록에 들어갈 때, 컴파일러는 auto 변수를 위한 기억공간을
할당하고 블록을 빠져 나올 때 할당되었던 기억공간을 회수한다.
•
그래서, 같은 블록을 두 번 수행하게 된다면 첫번째 수행에서 배정된 auto 변수의 값은 두번째 수행에서 남아있지 않게 된다.
• int a; /* 변수 a는 자료형이 정수고 기억영역 클래스는 auto */
• auto int a; /* int a 와 같은 문장이다. */
auto 변수 예제
{
int k;
for ( k = 1; k <= 10; k++) { int sum = 0;
sum = sum + k;
printf(“ sum = %d \n”, sum);
} }
auto int sum = 0;
static 변수
•
auto 변수와 반대의 효과를 갖는 기억영역 클래스
•
블록에서 변수가 static으로 선언되었다면 (예: static int a; ) 블록을 빠져 나가더라도 변수에 할당된 기억공간이 회수되지 않고 그대로 남아 있다.
•
따라서, 다음 번에 같은 블록을 수행하더라도 이전 번에 수행될 때 배정된 값이 static 변수에 여전히 남아 있게 된다.
•
예제 (다음 페이지)
static 변수 예제 (1)
{
int k;
for ( k = 1; k <= 10; k++) { static int sum = 0;
sum = sum + k;
printf(“ sum = %d \n”, sum);
} }
static 변수 예제 (2)
void f (void) {
static int count = 0;
count++;
if (count >= LIMIT)
………
else
………
}
int main(void) {
int k;
for ( k = 1; k <= 10; k++) { f( );
} }
extern 변수
#include <stdio.h>
int a = 1, b = 2, c = 3;
int h(void);
int main(void) { printf(“ %d\n”, h( ));
printf(“ %d, %d, %d\n”, a, b, c);
return 0;
}
int h ( void ) { int b, c;
a = b = c = 4;
return (a + b + c);
}
세 개의 정수 변수는 다른 함수들의 외부에서 선언된 global (전역)변수이다.
그래서, 이 세 변수는 모든 함수의 내부에서 유효하다.
a, b, c
extern 변수
•
정의된 모든 함수의 외부에 선언된 변수는 extern 변수라 부른다.
•
extern 변수를 선언할 때에는 모든 함수의 외부에 오도록 선언하면 된다. (예: 바로 전 페이지에서의 a, b, c 세 개의 정수 변수)
•
만약, 다른 파일(file)에서 extern 변수를 그대로 사용하고 싶다면, 사용하기 전에 extern int a, b, c 라는 문장을 미리 삽입해야 한다.
•
extern int a, b, c 라는 문장은 compiler에게 a, b, c 라는 변수가 다른 파일에 선언되어 있는지 검사하여 선언되어 있다면 그 변수를
사용할 것이라는 내용을 전달한다.
extern 변수
#include <stdio.h>
int a = 1, b = 2, c = 3;
int f(void);
int main(void) { printf(“ %d\n”, f( ));
printf(“ %d, %d, %d\n”, a, b, c);
return 0;
}
int f ( void ) { int b, c;
a = b = c = 4;
return (a + b + c);
}
file1.c
file2.c
Q: file2.c 에서 전역변수 a를 사용하고 싶다면?
A. 변수 a 가 다른 파일에서 전역변수로 선언되어 있고 그것을 사용하겠다는 내용의 문장을 삽입해야 한다.
Q: 그럼, 그 문장이란
A: extern int a; 라는 문장을 file2.c 의 처음에 삽입한다.
register 변수
•
a = b + c; 라는 문장의 내부적인 계산과정
1. 변수 b와 c의 값을 메모리에서 읽어 특별한 기억공간 (register)으로 가져온다.
2. 두 값을 더해서 새로운 register에 저장하고 그 값을 변수 a의 메모리에 다시 저장한다.
–
register는 계산을 신속히 하기 위해 특별히 설계된 CPU 내의 기억 공간이다.
–
register int a;
– 정수형 변수 a를 일반적인 memory에 기억공간을 할당하지 않고 register에 할당하게 된다.
– 이렇게 하면, a와 관련된 계산이 상대적으로 빨리 수행된다.