-
배열
-
크기가 같은 변수들이 메모리에 순차적으로 할당되어 있는 자료형
로또 프로그램을 만든다고 가정해보자.
우선 7개의 번호를 저장하기 위해 7개의 변수가 필요하다. (num1, num2, ... num7)
만일 7개가 아닌 n개의 값을 저장하려면? n개의 변수를 만들어야 한다.
이렇게 일일이 변수를 만드는 것은 매우 비효율적이다.
여기서 배열의 장점을 알 수 있다.
크기만 정해주면 원하는 만큼의 변수를 쉽게 만들 수 있다. (메모리 크기에 따라 다름)또한 값들이 메모리에 일련하게 저장되어 배열의 인덱스(offset)로 쉽게 찾아낼 수 있다.
하지만 배열은 정적 할당 변수이기 때문에 크기를 선언시에 지정해야 한다.
(이를 극복하기 위해 동적 할당을 이용한 연결 리스트가 있다.)
따라서 지정한 크기보다 데이터를 적게 사용할 경우에는 메모리가 낭비될 수 있다.
-
-
포인터
-
변수의 주소값(메모리 주소)을 저장하기 위한 변수
함수 안에서 선언된 지역 변수는 함수가 반환 될 때 메모리에서 사라진다.
입력으로 받은 변수의 값을 변경하려면 메모리 주소를 알아야 하는데 이 때 포인터를 이용할 수 있다.
또한 힙(Heap) 메모리 영역에 있는 변수의 값을 변경하고자 할 때 사용 가능하다.
(Java에서 new()를 이용해 만든 변수는 힙 영역에 저장되고 변수 이름으로 접근 가능하지만
C언어에서는 포인터로 접근한다.)
하지만 프로그래머가 메모리를 직접 접근한다는 것은 매우 위험한 행위다.
그래서 Java에서는 포인터 변수가 존재하지 않고 메모리는 JRE가 처리한다.
(접근 방식은 포인터 접근 방식과 같다.) -
※ 배열 원소 접근 : 배열 인덱스 vs 포인터
배열 arr은 메모리에서 arr 배열의 시작 주소 값을 가진다.
만약 배열 arr의 자료형이 Integer(4byte)이고, 값(시작 주소)이 0x4FFE28일 경우
arr[0]은 0x004FFE28에서 4 x 0을 더한 메모리 주소(0x004FFE28)에 저장되어 있는 값이다.
즉, arr[n]은 0x004FFE28 + (4 x n) 메모리 주소에 있는 값이다.
포인터도 배열과 같은 기능이 있다. 바로 산술연산을 통해 포인터 변수의 값을 변경하는 것이다.
+1, ++ 연산을 수행했을 때, 1의 값이 증가되는 것이 아니라 int*로 선언했기 때문에 값은 4씩 증가한다.
즉, 다음 두 소스 코드는 같은 동작을 한다는 것을 알 수 있다.
int i;
int arr[10];
for (i = 0; i < 10; i++) {
arr[i] = i + 1;
}
int i;
int arr[10];
int* p = arr;
for (i = 0; i < 10; i++) {
*p = i + 1;
p++;
}
그렇다면 왜 굳이 포인터를 이용해서 배열의 원소를 접근하는 것일까??
만약 정수형 배열의 원소 값들을 모두 더한다고(sum) 가정해보자.
인덱스를 이용할 경우 배열의 시작주소에서 (자료형의 크기 x 인덱스번호) 값을 더하여 접근한다.
반대로 포인터를 이용할 경우 매번 배열 주소를 계산할 필요가 없다.
포인터 변수의 값을 증가시키고 이를 이용하여 메모리에 접근하면 되기 때문이다.
하지만 이런 방식은 배열의 시작 주소를 다시 찾아내기가 불편할 수 있다.
즉, 배열의 원소를 접근할 때 이러한 지식을 바탕으로 상황에 맞게 배열 인덱스 접근 혹은 포인터 접근을
선택 할 수 있다.
※ 포인터 변수의 크기는?
int* p라고 선언한다면 이 변수의 크기는 4byte라고 말할 것인가?
(보통) 4byte가 맞다.
그렇다면 char* p라고 선언한다면 어떨까?
이것 또한 (보통) 4byte가 정답이다.
여기서 왜 (보통) 이라는 말을 작성했는지에 대한 궁금했을 것이다.
cpu는 메모리에서 데이터를 가져와 레지스터에 저장하고 처리한다.
x86(x32), x64 컴퓨터 중 어떤 것을 사용하느냐에 따라 데이터 처리 비트의 한계치가 다르다.
따라서 x32에서 포인터 변수의 크기는 4byte이고 x64에서는 8byte이다.
하지만 호환을 위해서 x64에서도 x32설정으로 컴파일하기 때문에 별도로 설정하지 않는다면 4byte이다.
'Language > C, C++, C#' 카테고리의 다른 글
[C] clock()을 이용한 타자연습기 만들기 (실행시간 측정) (0) | 2020.08.17 |
---|---|
[C] Sleep(), system("cls")를 이용한 주사위 굴리기 (0) | 2020.08.16 |
[C] 방향키로 printf() 커서 위치 이동 (gotoxy) (0) | 2020.06.09 |
[C] 아스키코드(ASCII)와 유니코드(Unicode)란? (0) | 2020.06.09 |
[C] 프로그램 실행 과정 (빌드 과정) (0) | 2020.06.08 |