컴퓨터/C
포인터와 배열의 개념을 이해를 했다면 이 둘을 조합하여 조금 더 프로그래밍적 기법들을 사용할 수 있습니다.
우선 이 둘에 대하여 다시 정리해 보도록 하겠습니다.
아래오 같은 배열을 선언했다고 하면 메모리에서 배열은 어떻게 존재할까요?
int arr[2] = {0,};
편의상 메모리 주소는 1byte씩 10진수로 표기했습니다. 요약하자면 아래와 같습니다.
위의 그림을 보면 배열은 선언한 자료형의 크기만큼 순서대로 메모리 위에 올라가 있는 것을 알 수 있습니다.
즉 배열이 시작되는 가장 첫 번째 메모리 주소와 자료형을 알고 있다면 각각의 배열의 인덱스에 접근할 수 있습니다.
실제로 배열에서 각각의 인덱스에 접근하기 위해 대괄호 [ ]를 사용하여 원하는 위치의 인덱스에 접근하게 됩니다.
말로 풀자면 다음과 같을 것입니다.
arr [0]
arr의 주소에서 자료형의 크기만큼 0번 지난 후 자료형의 크기만큼 읽어줘
이해가 어려울 수 있으니 다시 한번 선언한 배열 arr을 이해해 보도록 하겠습니다.
이런 식으로 배열의 접근법을 풀면 위의 설명과 같습니다.
그럼 포인터는 메모리의 주소를 저장한다고 했습니다. 만약 포인터 변수에 배열의 시작 주소를 저장한다면 배열처럼 제어가 가능할까요?
int arr[2] = {0,};
int* p = &arr;
이제 포인터 변수 p안에 들어있는 메모리 주소와 배열 arr의 메모리 주소는 동일합니다.
그리고 포인터 변수를 통해 arr [0]만을 제어할 수 있습니다.
여기서 배열처럼 포인터 변수도 n번째 자료형 크기 뒤의 정보를 읽어오게 할수 있습니다. 이것을 C언어에서는 주소 연산이라고 합니다.
int arr[2] = {0,};
int* p = &arr;
p+1; // 메모리 주소연산
int*형 포인터 변수를 선언했기 때문에 포인터 변수에 저장된 주소부터 4byte를 읽는 포인터 변수입니다.
이 포인터 변수에 +1을 더한다는 것은 자료형의 크기만큼 메모리 주소를 더한다는 의미입니다.
즉 +1은 +int(4byte)의 개념이 되는 것입니다.
실제로 배열에 접근이 되었는지 확인해보도록 하겠습니다.
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int arr[2] = { 0,1 };
int* p = &arr;
printf("%d\n", *p);
printf("%d\n", *(p + 1));
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int arr[2] = { 0,1 };
int* p = &arr;
printf("%d\n", p[0]);
printf("%d\n", p[1]);
printf("%d\n", *(arr + 0));
printf("%d\n", *(arr + 1));
return 0;
}
C언어를 통해 프로그래밍을 배우고 있다면 결국 데이터들은 메모리 안에서 어떻게 정의되어 사용하는지에 대하여 이해를 어느 정도 했을 것입니다.
그리고 포인터와 배열을 이해하고 사용했다면, 표현의 방법의 차이가 있을 뿐이지, 결국은 메모리 공간을 어떻게 정의하고 사용할지에 대한 개념일 뿐입니다.
이런 내용들을 이해하고 있다면 아래와 같은 방법으로 표기를 해도 사용 가능할 수 있다는 것을 예상할 수 있습니다.
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
int arr[2] = { 0,1 };
int* p = &arr;
printf("%d\n", p[0]);
printf("%d\n", p[1]);
printf("%d\n", *(arr + 0));
printf("%d\n", *(arr + 1));
return 0;
}
결국 개념적인 부분에서 배열과 = 포인터는 같다.
따라서 표현 방법 또한 혼용이 가능하다.
결국 이런 개념들이 발전하고 사용하는 데는 다 이유가 있습니다.
그럼 오늘 배운 것들을 한번 이용해서 사용하면 장점이 무엇인지 알아보도록 하겠습니다.
간단한 예시로 배열의 값을 함수에서 제어하는 소스코드를 만들어 보도록 하겠습니다.
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void arrset(int* arr , int size)
{
for (int i = 0; i < 10; i++)
{
*(arr + i) = i;
}
}
int main()
{
int arr[10] = { 0 };
for (int i = 0; i < 10; i++)
{
printf("함수 실행 전 arr[%d] : %d\n", i, arr[i]);
}
arrset(&arr, 10);
for (int i = 0; i < 10; i++)
{
printf("함수 실행 후 arr[%d] : %d\n", i, arr[i]);
}
return 0;
}
위의 소스처럼 배열의 인덱스는 1부터 1씩 증가하면서 초기화하는 함수를 만들었습니다.
물론 main함수 안에서 구현을 할 수 있지만, 만약 100개의 배열을 초기화하기 위해서는 main함수에서 구현하기란 상당히 어려운 일입니다. 또한, 포인터와 주소 연산의 개념을 모른다면 배열을 한 번에 제어하는 함수를 만들기는 쉽지 않을 것입니다. 이런 한계들을 극복하여 좀 더 효율적인 소스코드를 만들 수 있습니다.
C 언어 - typedef 키워드 (0) | 2021.06.22 |
---|---|
C 언어 - struct(구조체) (0) | 2021.06.22 |
C 언어 - const 키워드 (0) | 2021.06.18 |
C 언어 - 형변환(Casting) (0) | 2021.06.17 |
C 언어 - 오버플로우와 언더플로우 (0) | 2021.06.16 |
91년생 공학엔지니어의 개발일지
TODAY :
YESTER DAY :
TOTAL :
Commnet