728x90
반응형
포인터 산술
- 포인터에 덧셈을 할 수 있으며, 그 결과는 데이터 타입에 따라 달라진다.
즉, 포인터 산술을 진행하면 다음 데이터를 가리키는 것으로 생각하자.
int 는 메모리에서 4byte 할당
char 은 메모리에서 1byte 할당
double 은 메모리에서 8byte 할당
- 배열의 이름은 배열 첫 번째 요소의 주소를 의미한다.
arr + 1 = &arr[0] + 4 = &arr[1]
포인터 산술 - 증감 연산자
괄호를 쳐서,
연산 순위를 헷갈리지 않도록 사용하자.
포인터 산술 - 증감 연산자
배열과 포인터의 차이점 || 중요~
- 배열의 이름은 배열의 시작 주소를 가리키는 상수 포인터
- 상수는 L-value로 사용할 수 없다.
- 즉, 등호의 왼쪽에 올 수 없다.
상수는 프로그램 실행 중 바꿀 수 없는 값을 의미한다.
등호의 왼쪽에 온다는 것은 새로운 값을 할당하겠다는 의미이기 때문이다.
- 반면, 포인터는 변수이므로, L-value로 사용할 수 있다.
- 등호의 왼쪽에 올 수있다.
2중 포인터
포인터 자체도 변수이며 메모리에 저장된다.
즉, 주소를 갖는다.
2중 포인터는 포인터 변수를 가리키는 포인터를 의미한다.
- 2중 포인터 변수에는 포인터가 저장된 주소를 담고 있다.
포인터 변수의 데이터 크기
포인터 변수 자체의 크기는 가리키고 있는 데이터의 타입의 크기와 다르다.
주소를 저장하는데 4byte가 필요하다고 가정
포인터 변수는 주소 하나를 저장할 만큼 공간이 필요하다.
# 5000개의 배열이 있다고 하면,
이를 바꾼다고 가정한다면, 함수 호출 한번으로 5000개의 배열을 재구성할 수 있다.
(아래의 예제를 통해 2중 포인터에 대해서 이해해보자)
동적 메모리 개요
배열은 사용하기 전에 그 크기를 정확히 알려줘야 했다.
- 컴파일러가 '프로그램을 실행하기 이전'에 스택 프레임 크기를 고정시켜 놓기 위함이다.
반면, 힙 메모리(= 동적 메모리)는 '프로그램을 실행하는 동안' 필요한 만큼의 변수 공간을 할당 받을 수 있다.
- 힙 메모리와 스택메모리는 별도로 관리한다.
- 힙 메모리에 생성한 데이터는 스택 프레임이 제거되어도 프로그램이 종료될 때까지 메모리에 상주한다.
- 제거를 의해서는 별도의 명령이 필요하다.
동적 메모리 할당 받기
힙 메모리를 할당 받으려면 malloc (memory allocation) 함수 사용
# 동적 메모리 할당을 구현하는 방법
# include <stdlib.h>
(void *)malloc(size_t size);
typedef unsigned int size_t;
# 동적 메모리 할당
동적 메모리의 생명주기 - 동적 메모리의 예외처리
#include <stdio.h>
#include <stdlib.h>
int* get_number() {
int* p = (int*)malloc(sizeof(int));
if (p == NULL){ // NULL test
printf ("No more memory available. \n");
exit(1);
}
*p = 20;
return p;
}
int main() {
int i, *ptr;
ptr = get_number();
printf("%d.\n", *ptr);
free(ptr);
ptr = NULL;
return 0;
}
NULL test가 필요한 이유
동적 메모리는 프로그램 실행 도중 크기를 정하기 때문에 적합한 공간이 없을 수 있다.
- 이때 malloc은 NULL 값을 반납한다.
- NULL은 0을 의미하며, 0번지에 값을 저장할 때 크래시가 발생한다.
- 이를 방지하기 위해 malloc 후 NULL test를 반드시 해야한다.
정적 배열과 동적 배열의 차이
- 정적 배열은 컴파일 타임에 미리 크기가 정해진다.
- 프로그램 실행 도중에 크기를 바꿀 수 없다.
- 사용자로부터 입력을 받는다면 크기를 넉넉히 만들어야 하므로 낭비가 발생한다.
- 정해진 크기가 스택에 올리면 되기 때문에 빠른 처리가 가능하다.
- 스택 프레임의 생성과 소멸에 따라 자동으로 메모리 관리한다.
- 동적 배열, 즉 동적 메모리는 런 타임에 크기가 정해진다
- 프로그램 실행 도중 크기를 바꿀 수 있다.
- 필요한 만큼만 조절해서 만들면 되므로 메모리 낭비가 없다.
- 프로그램 실행 도중 적합한 공간이 있는지 확인한 후 할당해야 하므로 상대적으로 느리다.
- 직접 생성 (malloc)하고, 직접 제거(free) 해야 한다.
동적 배열을 생성할 때는
NULL Test를 진행해서 메모리 공간에 배열을 할당할 수 있는지 테스트를 한다.
테스트를 통과하면, 동적 배열을 생성하고,
테스트를 통과하지 못하면, 동적 배열을 생성시키지 않는다.
이는, 동적 배열을 할당할 때 메모리에 대한 공간이 여유롭지 않을 때
NULL 값으로 메모리 공간이 할당되고, 이를 주숫값으로 지정하지 못하도록 예외처리를 하는 것이다.
마치며,
C언어 포인터에 대해서 본격적으로 심화를 다루고있다.
처음 듣는 지금은 많이 추상적이다.
포인터가 정확히 먼지도 모르겠고, 어떨 때 사용되는지도 감이 안잡혔다.
그치만, C언어 포인터 강의를 처음부터 다시 들어보면서 포인터에 대해 익숙해지도록 하겠다.
원래 뭐든지 처음엔 어설프게하고,
처음엔 어려운 법이니 포기만 하지말자.
C언어 공부할 시간이 마땅치 않을텐데, 그래도 수업시간에 최대한 열심히 들으면서
이해의 폭을 더 넓히도록 하겠다.
11월 화이팅!
728x90
반응형
'CS 대학강의' 카테고리의 다른 글
[CS 1-2 | 프로그램 설계 방법론] Java GUI 12주차 (0) | 2022.11.03 |
---|---|
[CS 1-2 | 대학생을 위한 실용금융] 투자의 정리 8주차 (0) | 2022.11.02 |
[CS 1-2 | 프로그램 설계 방법론] Java 인터페이스와 상속 10주차 (0) | 2022.10.27 |
[CS 1-2 | 오픈소스 SW 기초] 가상화 & 리눅스 컨테이너 with Docker 6주차 (0) | 2022.10.20 |
[CS 1-2 | 프로그램 설계 방법론] Java로 병원 입원 관리 서비스 제작 (0) | 2022.10.20 |