변수의 영역
변수를 어떻게 분류할 것인가?
- scope : 보이냐, 보이지 않느냐 - 전역(블록 밖에 존재 - .data 섹션), 지역(블록 안에 존재 - 일반적으로 stack에 배정), 함수(scope : 전역), etc
- life time : 메모리 상에 값을 언제까지 가지고 있는가? - storage class(storage - keyword | 1. stack - auto, 2. data, bss - global, static 3. register - register 4. other .c file)
변수의 linkage
자기가 속해 있는 블럭부터 밖으로 나가면서 찾는다.(local -> global)
함수의 경우 - C에서 함수는 모두 전역이다.
정적 지역 변수(static) : storage 자체는 전역 변수와 같다. 그러나 볼 수 있는 범위는 지역 변수와 같이 블럭 밖에서 블럭 안을 보지 못한다. static의 범위는 하나의 파일이다. 이 점에서 모든 프로그램에서 접근이 가능한 전역 변수와는 차이점이 있다.
void func(){
static int i = 0; //지역 변수이기는 하지만 전역 변수와 라이프 타임이 유사하다.
=> .data 섹션에 잡혀있다.
그러나 찾을 수 있는 scope는 여전히 블록 안이다.
printf("%d", i++);
}
int main(){
func(); func(); func(); // 1 2 3
return 0;
}
BSS 영역에 저장되어 있는 데이터는 저장 용량에 영향을 미치지 않는다.
**** deeper insight
case 1) main에서 함수를 세 번 call한 경우
void ss(){
static int i = 0;
d(i, i++); // 정수, 정수를 출력하는 함수
}
// main에서 실행하면 1, 2, 3 출력
case 2) main에서 실행한 경우
{
static int i = 0;
d(i, i++); // 정수, 정수를 출력하는 함수
}
{
static int i = 0;
d(i, i++); // 정수, 정수를 출력하는 함수
}
{
static int i = 0;
d(i, i++); // 정수, 정수를 출력하는 함수
}
계속 0만 출력된다.
static 변수의 선언은 프로그램 자체에 해당 메모리 영역에 지정하라는 것일 뿐, instruction이 아니다.
스코프는 메모리를 할당할 때 영향을 준다. -> 그렇기에 변수 타입과 변수명이 같더라도
블럭 스코프가 다르면 다른 메모리 영역에 저장된다.
call by value vs call by reference : C는 포인터를 지원하므로, 포인터를 이용하여 주소만 전달하면 값을 카피할 필요가 없다. C는 기본적으로 call by value이다.
다차원 배열과 포인터
이중 배열의 연장선이다. 포인터와 배열이 무엇을 가리키는지 파악하면 해결되는 일이다.
이중 배열과 포인트 배열의 차이는 데이터가 메모리에 할당되는 방식에 있다.
응용 포인터
이중 포인터, 삼중 포인터 : 그림 참고, 포인터의 개념에서 벗어나지 않음
int x[a][b] => int[b] x[a] => int[b][] x => int[b]* x = > int* x[b] => int (*x)[b]
배열을 포인터로 온전히 받을 수 없는 이유는 배열과 포인터의 메모리 저장 방식이 다르기 때문이다. 배열은 말그대로 데이터들이 연속적으로 저장된 메모리 블럭 형태로 저장되고, 포인터는 주소를 저장하기 때문이다.
- 2D 배열에서는 "행을 가리키는 포인터"를 swap하여 배열을 교환할 수 있다.
- 3D 배열에서는 swap하려는 것이 "2D 배열 묶음"인데, C에서는 이를 직접 가리킬 수 있는 포인터 타입이 없기 때문에 swap이 불가능하다.
- 정적 배열은 메모리 주소가 고정되어 있으므로, 포인터 swap만으로 배열을 교환할 수 없다.
→ 따라서, 3D 배열 이상의 정적 배열은 memcpy()를 사용하여 직접 내용을 교환해야 한다.
파라미터에 편의상 arr[n1][n2][n3]을 파라미터로 받는데 배열이 상수인 점을 생각하면, 실제는 포인터이고 바람직한 표현은 아니다.
****이중배열의 타입 캐스팅 : ( type (*) [N] )*** | ****변수명을 제외하고는 변수 타입이라고 생각해도 됨****
//일차원 배열을 void* 로 입력 받아서, 이중배열로 타입캐스팅한 후 출력
void printArray3(void *p){
int i, j;
for(i = 0; i < 3; i++){
for(j = 0; j < 4; j++){
printf("%d ", ((int(*)[4])p)[i][j]);
}
puts("");
}
}
이런 게 가능하다. 기본이 중요한 것 같다.
'VEDA 복습' 카테고리의 다른 글
VEDA 3일차 - C 프로그래밍 (0) | 2025.03.19 |
---|---|
VEDA 2일차 - C 프로그래밍 (0) | 2025.03.18 |
VEDA 1 일차 : C 프로그래밍 (0) | 2025.03.17 |