20260502 프로그래밍기초 9주차
강의 핵심 요약 — 배열(고급), 포인터, 메모리 구조, VLA
이번 강의는 단순 배열 문법이 아니라:
배열 = 메모리 구조
관점으로 보는 게 핵심이었음.
특히:
- 배열과 포인터 관계
- 2차원 배열 메모리 구조
- 행 우선(Row-Major)
- 배열 포인터
- VLA(가변 길이 배열)
- Stack vs Heap
이 부분이 핵심.
1. 배열의 진짜 의미
초급에서는:
int arr[10];
하면:
정수 10개 저장
정도로 이해했음.
근데 고급에서는:
연속된 메모리 블록
으로 이해해야 함.
2. Array Decay (배열의 퇴화)
핵심 개념.
배열 이름은 특정 상황에서:
포인터처럼 변함
예:
int arr[5];
함수에 전달되면:
arr
은 사실상:
&arr[0]
처럼 동작함.
3. 배열과 포인터 차이
많이 헷갈리는 부분.
배열
int arr[5];
- 실제 메모리 공간 존재
- 크기 고정
포인터
int *p;
- 주소만 저장
- 실제 데이터 공간 아님
4. 2차원 배열 메모리 구조
예:
int matrix[3][4];
메모리에서:
1 2 3 4 5 6 7 8 9 10 11 12
이렇게 연속 저장됨.
즉:
행 단위로 저장
됨.
5. Row-Major Order (행 우선 저장)
C언어 핵심 특징.
matrix[0][0]
matrix[0][1]
matrix[0][2]
...
순으로 메모리 배치됨.
즉:
한 행을 먼저 전부 저장
함.
6. 왜 Row-Major가 중요한가
성능 때문.
예:
for(i=0;i<ROWS;i++)
for(j=0;j<COLS;j++)
matrix[i][j];
이건 메모리 순서대로 접근.
반대로:
for(j=0;j<COLS;j++)
for(i=0;i<ROWS;i++)
matrix[i][j];
이건 점프하면서 접근.
결과:
캐시 효율 급감
함.
7. 배열 포인터
여기 시험 단골 가능성 높음.
핵심
int (*arr)[COLS];
이건:
배열 전체를 가리키는 포인터
임.
8. 많이 틀리는 부분
배열 포인터
int (*arr)[COLS];
의미:
COLS 크기 배열을 가리키는 포인터
포인터 배열
int *arr[COLS];
의미:
포인터 여러 개 저장하는 배열
완전히 다름.
9. 포인터 연산으로 2차원 배열 접근
일반:
matrix[i][j]
포인터 방식:
*(*(arr+i)+j)
10. 왜 이렇게 동작하는가
1단계
arr + i
→ i번째 행 이동
2단계
*(arr+i)
→ 해당 행 시작 주소
3단계
*(arr+i)+j
→ j번째 열 이동
4단계
*(*(arr+i)+j)
→ 실제 값 접근
11. VLA (Variable Length Array)
가변 길이 배열.
C99에서 등장.
기존 배열
int arr[10];
컴파일 시 크기 결정.
VLA
int n;
scanf("%d",&n);
int arr[n];
실행 중 크기 결정 가능.
12. VLA 핵심 특징
런타임 생성
사용자 입력 기반 가능.
Stack 사용
여기 중요.
VLA는:
스택(Stack)
사용함.
13. Stack vs Heap
Stack
특징:
- 자동 관리
- 매우 빠름
- 공간 작음
- 함수 종료 시 자동 제거
저장:
- 지역 변수
- 매개변수
- VLA
Heap
특징:
- malloc 사용
- 직접 free 필요
- 느리지만 큼
- 동적 메모리 가능
14. VLA와 malloc 차이
VLA
int arr[n];
- stack 사용
- 자동 해제
- 빠름
malloc
int *arr = malloc(sizeof(int)*n);
- heap 사용
- free 필요
- 큰 메모리 가능
15. 왜 VLA 위험한가
Stack은 작음.
예:
int arr[10000000];
같은 거 만들면:
Stack Overflow
가능.
16. scanf vs scanf_s
강의 중 추가 설명.
숫자 입력
scanf("%d",&age);
문제 거의 없음.
문자열 입력
scanf("%s", name);
버퍼 크기 몰라서 위험.
scanf_s
scanf_s("%s", name, sizeof(name));
버퍼 크기 전달.
더 안전함.
17. VLA 메모리 특징
핵심:
int scores[size];
는 여전히:
배열
임.
그래서:
sizeof(scores)
가능함.
18. 자동 메모리 관리
VLA는:
free() 필요 없음
함수 끝나면 자동 제거됨.
이게 heap과 차이.
19. VLA 제한 사항
전역 변수 불가
int n=10;
int arr[n];
전역에서는 안 됨.
static 사용 불가
static int arr[n];
안 됨.
컴파일러 호환성 문제
C11 이후:
선택 기능(Optional)
됨.
즉:
- GCC → 지원 잘 함
- 일부 MSVC → 미지원 가능
20. 교수 핵심 메시지
이번 강의 핵심은:
배열을 "데이터 묶음"이 아니라
메모리 주소 체계로 이해하라
였음.
시험 관점 핵심
진짜 중요한 부분:
배열과 포인터
- Array Decay
- 배열 이름 = 시작 주소
2차원 배열
- Row-Major
- 연속 메모리 구조
배열 포인터
int (*arr)[COLS]
이거 의미.
포인터 연산
*(*(arr+i)+j)
해석 가능해야 함.
VLA
- Stack 사용
- 자동 해제
- 런타임 크기 결정
Stack vs Heap
- 자동 관리 vs 수동 관리
- 속도 vs 유연성 차이
특히:
int *arr[COLS]
int (*arr)[COLS]
이 둘 차이 이해 못하면 뒤에서 포인터 거의 다 꼬임.