본문 바로가기
  • hazard_dev@__
  • hazard_dev@__
C

배열과 포인터(array , pointer) 천천히~

by Hazard3_o00sung 2020. 2. 14.
728x90

본 포스트는 c언어를 중심으로 작성되었음을 알려드립니다.

 

배열과 포인터(array , pointer) 천천히~


1. 배열

우선 배열에 대해서 알아봅시다. 배열은 같은 자료형이 나열되어 메모리에 연속적으로 저장된 자료형입니다. 

 

만약, 과일의 종류를 담는 변수를 선언할 때 어느 것이 효율적일지 한번 생각해보세요.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
int main (){
 
    char str[] = "apple";
 
    char str2[] = "orange";
 
    char str3[] = "cherry";
 
    printf("%s %s %s\n", str, str2,str3);
 
    return 0;
 
}
 
 
 
cs

위와 같이 일일이 선언 하는것 보다 한번에

char str4[] = {"apple" ,"orange", "cherry"}; 라고 선언 해주는게 훨씬 효율적입니다.

 

또한 배열선언의 메모리 할당 크기는 자료형에 대한 크기에 따라 메모리 할당 크기는 달라집니다.

 

예를 들면, int i[100]; 이라는 정수형 배열요소를 선언한것은, 100개로 구성된 배열 i이며 동시에 메모리 할당크기는 4byte(size int) * 100 이 됨을 알 수 있습니다.

 

배열의 초기화는 아주 간단하게 초깃값을 지정하면서 초기화 할 수 있습니다.

 

자료형(int) 배열이름(str)[배열크기] = {초깃값};

예) int a[5] = {1,2,3,4,5};

 

위와 같은 형태로 선언하여 초깃값을 지정합니다.

 

1-1. 문자배열

말 그대로 문자를 나열한 배열입니다. 배열의 자료형은 char이 되며, 초기화는 그대로 지정해서 사용해도 되고 초깃값 문자 리스트를 사용하거나 무방합니다!

 

예를 들면,

char s1[10] = "apple";

 

이라면 문자열을 이용한 초기화입니다.

 

char s2[10] = {'a','p','p','l','e'};

 

라고 선언이 되었다면 문자리스트를 사용한 초기화입니다. 차이점은 문자열이 저장될때는 문자열의 맨 마지막 인덱스는 null을 가르킵니다. 말 그대로 실제 문자열 크기보다 1만큼 사이즈가 더 크다는것을 의미합니다.

 

1-2. 다차원배열

 

배열은 다양하게 구성할 수 있는데 그 중에서 2,3차원 배열로 선언하여 사용이 가능합니다.

우선, 2차원배열은

 

자료형(int) 배열이름 (str) [배열크기][배열크기]; 로 선언하여 사용합니다

 

 다음의 배열은 int str[4][4];로 선언되어 생성된 2차원 배열입니다. 논리적 구조는 행렬의 형태를 기억해내셔서 만들어내면 간단합니다!

 

3차원 배열은 조금 복잡할 수 있습니다. 선언 형식에서 차수가 추가된 만큼 배열크기를 하나 더 선언 해주셔야 합니다.

 

자료형(int) 배열이름 (str) [배열크기][배열크기][배열크기]; 로 선언합니다.

 

 

 

면개수, 행개수, 열개수로 나뉘어 논리적구조로 표현하면 위 그림과 같습니다.

앞면은 면 0이라 하고 뒷 면을 면1이라고 생각하면됩니다. 

표현식은 다음과 같습니다.

 

int str[2][4][4];

 

개인적으로는 3차원 배열을 이해하기 까다롭습니다. 특히나 이렇게 간단하게 표현한 시각물에서는 그렇구나 하고 느끼지만, 실제적으로 활용을 할때 매우 까다롭습니다.

 

그래서 예제 코드를 준비해보았습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
 
int main()
 
{
 
    int i,j,k,value = 1;
 
    int array[2][3][4];
 
    for(i = 0; i<2; i++){
 
        for(j =0; j<3; j++){
 
            for(k=0; k<4; k++){
 
                array[i][j][k] = result;
 
                printf("\n Array[%d][%d][%d] = %d"
 
                ,i,j,k,array[i][j][k]);
 
                result++;
 
            }
 
        }
 
    }
 
    return 0;
 
}
 
}
 
 
 
cs

위 코드를 직접 보시고 한번 따라해보세요. 중첩반복문을 사용하여 다차원 배열에 엑세스 한 다음 각 면행렬인덱스 값에 대응되는 값을 저장하는 아주 간단한 코드입니다.


2. 포인터

저 같은 경우는 프로그래밍 언어의 출발을 js,python으로 해서 포인터 개념을 이해하기 까다로웠던것 같습니다. 저만의 방식대로 정리해보겠습니다 ㅎㅎ.

 

우리가 사용하는 모든 변수는 메모리의 특정 위치에 저장되고 그 위치를 표현하는 메모리 주소를 포인터라고 일컫습니다. 포인터 변수는 다른것을 담는것이 아닌 오직 하나의 메모리 주소값을 저장하는 좀 특이한 변수라고 볼 수 있습니다.

 

예를 들면,

 

제가 장을 마트에 보러 가는 상황을 가정하여 설명하겠습니다.

짐이 너무 무거워 도저히 들고 올 수 있는 상황 또한 안됩니다. 이럴땐 퀵 서비스를 이용하는것이 효율적이겠죠? 그렇다면 제가 저희 집 주소를 적은 쪽지를 기사님께 감사히 전달 합니다. 

 

위 상황에서의 쪽지는 포인터입니다. 쪽지 내 주소는 포인터에 저장된 변수의 메모리 주소입니다. 주소로 제가 물건을 받게 되면 포인터를 통한 엑세스라고 볼 수 있습니다!

 

그렇다면 코드 상에서는 어떻게 표현될지 보겠습니다.

 

int i; <-- i라는 변수를 선언합니다. a의 주소를 알아보기 쉽게 1080이라고 가정합니다.

int *ptr = &i; <-- ptr이라는 변수이름앞에 선언 된 아스테리스크가 바로 '내가 바로 포인터 변수다' 라는 것을 알려주는 기호입니다. 그리고 i앞에 붙은 엔퍼센드는 i의 주소를 참조하는 기호입니다.


2-1. 포인터 연산(& , *)

 

주소연산자 &(엔퍼센드)는 변수의 주소를 얻는데 사용하며, 참조연산자 *(아스테리스크)는 다른 변수의 주소가 저장된 포인터에 참조 연산자를 사용하여 저장된 주소 영역에 엑세스 할 수 있습니다.

 

2-2. 포인터 초기화

 

포인터를 초기화 하는 방법 또한 일반 변수를 초기화 하는 방법과 동일합니다.

다만 다음과 같이 초기화를 한다면, 오류가 날것입니다.

 

int *str = 5;

 

메모리주소를 참조하는 str변수가 5라는 메모리주소를 가르킨 다는 의미입니다. 5라는 주소가 있을수도 있지만! c이론을 접해보신 분이라면 알다시피 주소가 매번마다 변경되기때문에 사용자가 임의로 지정하는 것은 위험합니다.

 

그렇다면 어떻게 지정하는지 보겠습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
 
int main()
 
{
 
    int i;
 
    int *str = &i; //주소 연산자를 이용하여 변수 주소를 지정합니다.
 
    char *str = (char *)malloc(100); //혹은 동적메모리를 malloc함수를 통하여 문자열 공간 100개를 할당 시키고 str에 지정합니다
 
    char *str = "hello"//문자열 자료형은 지정만으로 주소전달이 되기에 hello문자열의 첫 인덱스 주소가 str에 저장됩니다.
 
    char a[100];
 
    char *str = a; //배열 이름은 문자열과 마찬가지죠, a는 100개의 char요소를 가지고 있고, str은 a의 첫 주소를 저장하며 엑세스합니다.
 
    char a[100];
 
    char *str = &a[0];// 배열의 시작은 첫번째 요소이기 때문에 a의 첫번째 요소만 전달해도 주소가 저장됩니다.하지만 주소연산자를 사용하여
 
//엑세스 하여야 그 값 자체를 전달가능합니다.
 
}
 
 
 
cs

위 와같은 방법을 통한 초기화를 하시면 됩니다!!

 

 

 

간단명료하게 설명하려 해보았지만, 워낙에 광범위 하여 축약하는것이 참 힘들었습니다^^. 저도 실력이 좋은 편은 아니지만, 저만의 팁이 있다면, 포스트에도 계속 나오듯이 사회적 현상에 빗대어 생각하는것 만큼 좋은것이 없는것 같습니다. 물론 이론적 이해도 반드시 필요함은 기본이겠죠?

 

궁금한 사항 댓글 부탁드리고, 언제나 피드백 환영합니다.

 

읽어주셔서 감사합니다.~

728x90

댓글