[고급 C++]포인터 2편(배열과 포인터)

  배열과 포인터

1차원 배열과 포인터

 배열 특성

- 배열의 이름은 배열의 시작주소(num = &num[0] =배열의 시작주소)

- 연속적인 메모리 할당 보장

     1  #include <stdio.h>

     2  int main()

     3  {

     4     int num[5] = {100, 200, 300, 400, 500}, i;

     5     int *p1;

     6

     7     printf("%d, %d \n", sizeof(num), sizeof(num[0]));

     8

     9     printf("\n");

    10     for(i = 0; i < 5; i++)

    11        printf("%p: %d \n", &num[i], num[i]);         // 연속된 메모리 보장

    12

    13     return 0;

    14  }

:!a.out

20, 4


7ffff0f0
: 100

7ffff0f4: 200

7ffff0f8: 300

7ffff0fc: 400

7ffff100: 500

 

- 배열은 포인터와 밀접한 관계를 가지며 배열을 포인터 변수를 이용하여 제어 가능

 count + i = ptr + i = &count[i] = &ptr[i] : 배열의 i+1번째 위치 주소
*(count + i) = *(ptr + i) = count[i] = ptr[i] : 배열의 i+1번째 위치 데이터

     1  #include <stdio.h>

     2  int main()

     3  {

     4     int num[5] = {100, 200, 300, 400, 500}, i;

     5     int *p1;

     6

     7     printf("%d, %d \n", sizeof(num), sizeof(num[0]));

     8     printf("%d, %p, %p \n", num[0], &num[0], num);

     9     // 첨자가 없는 배열변수는 그 배열이 할당된 메모리의

    10    // 시작주소를 갖는 포인터 상수이다.

    11

    12     p1 = num;

    13     printf("\n");

    14     for(i = 0; i < 5; i++)

    15        printf("%p: %d, %d, %d, %d %p %d\n",

    16        &num[i], num[i], *(p1+i), *p1+i, *(num+i), num+i, p1[i]);

    17        // 컴파일 과정에서 대괄호는 전부 포인터식으로 변환 (num[2] → *(num+2))

    18     return 0;

    19  }

 

:!a.out

20, 4

100, 7ffff0f0, 7ffff0f0

 

7ffff0f0: 100, 100, 100, 100 7ffff0f0 100

7ffff0f4: 200, 200, 101, 200 7ffff0f4 200

7ffff0f8: 300, 300, 102, 300 7ffff0f8 300

7ffff0fc: 400, 400, 103, 400 7ffff0fc 400

7ffff100: 500, 500, 104, 500 7ffff100 500

* %s : 입력받은 주소부터  ‘\0’까지 문자열로 출력

 

 

- 배열을 함수의 인수로 전달해야할 경우 배열은 배열전체가 복사되어 전달되는 것이 아니라 배열 시작 주소만이 전달되므로 배열을 받을 함수의 매개변수는 포인터로 선언되어야 함

* 배열(주소) 뿐만 아니라 배열의 크기도 함께 전달해야 사용 가능

     1  #include <stdio.h>

     2

     3  int main()

     4  {

     5     int sal[5]={1500,4300,5000,2700,4200}, i;

     6     int siz = sizeof(sal)/sizeof(sal[0]);      //  배열의 크기(개수) =  전체 배열 크기 / 배열 하나 크기

     7     printf("sal : %p %d \n", &sal, sizeof(sal));

     8   

     9     salCalc(sal, siz);    // 배열 전달, 배열의 크기 도 같이 전달해야함

    10

    11     return 0;

    12  }

    13

    14  // 월급평균을 계산

    15  salCalc(int *tmp, int tmpSiz)

    16  {

    17     int i, salTot=0;

    18

    19     for(int i=0;i<tmpSiz;i++)

    20     {

    21        printf("%d ", *(tmp+i));

    22        salTot += *(tmp+i);

    23     }

    24

    25     printf("\n");

    26     printf("월급평균 : %.2f \n", (float)salTot/tmpSiz);

    27  }

:!a.out

sal : 7ffff0f0 20

1500 4300 5000 2700 4200

월급평균 : 3540.00

 

* 응용 : 한글자 찍는 문제

- p2 주소가 NULL이면 주소값은 0이 아니므로 while문 종료

while(*p2)
{
        printf(“%c “, *p2);
        p2++;
}

 

- 배열명도 배열의 시작주소를 갖는 포인터 상수이기 때문에 포인터연산( *(num+1) )을 통해 배열에 접근할 수 있으나,

- 배열명은 포인터 상수이기 때문에 그 주소의 값을 변경하거나 새로운 주소를 저장할 수 없음. 즉, 주소이지만 constant이므로 배열변수는 증감불가

while(*str)
{
        printf(“%c “, *str);
        str++;
}

에러!

 

 

2차원 배열

형태

- 1차원배열 : a2[열];

- 2차원배열: a3[행][열]; (대괄호 2개)

- 3차원배열 : a4[면][행][열]

 

 

특성

- 배열은 포인터와 밀접한 관계를 가지며 배열을 포인터 변수를 이용하여 제어 가능

 count[i][j]는 *(*(count+1)+j)과 동일함
 &count[i][j] 주소는 *(count+i)+j와 동일함

     1  #include <stdio.h>

     2

     3  int main()

     4  {

     5

     6     int count[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12}, i, j;

     7

     8     // 배열이름과 첫배열주소는 같음

     9     printf("%d %d \n", sizeof(count), sizeof(count[0][0]));

    10     printf("%d %p %p \n", count[0][0], &count[0][0], count);

    11

    12     printf("\n");

    13     for(i=0;i<4;i++)

    14     {

    15        for(j=0;j<3;j++)

    16           printf("%p:%d \t", &count[i][j], count[i][j]);

    17        printf("\n");

    18     }

    19

    20     printf("\n");

    21     for(i=0;i<4;i++)

    22     {

    23        for(j=0;j<3;j++)

    24           printf("%p:%d \t", *(count+i)+j, *(*(count+i)+j));

    25        printf("\n");

    26     }

    27

    28     return 0;

    29  }

 

 

:!a.out

48 4

1 7ffff0e0 7ffff0e0

 

7ffff0e0:1      7ffff0e4:2      7ffff0e8:3

7ffff0ec:4      7ffff0f0:5      7ffff0f4:6

7ffff0f8:7      7ffff0fc:8      7ffff100:9

7ffff104:10     7ffff108:11     7ffff10c:12

 

7ffff0e0:1      7ffff0e4:2      7ffff0e8:3

7ffff0ec:4      7ffff0f0:5      7ffff0f4:6

7ffff0f8:7      7ffff0fc:8      7ffff100:9

7ffff104:10     7ffff108:11     7ffff10c:12


// 메모리에 차례대로 할당받음을 보장

 

- 첨자가 없는 배열변수는 데이터가 아닌 그 배열의 시작주소를 나타내며, 2차원 배열에서 배열 변수명과 첨자를 하나만 사용하는 것은 배열의 행을 의미

- 행은 데이터가 아닌 각 행이 시작되는 메모리의 주소임

     6     int count[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12}, i, j;

     7

     8     // 배열이름과 첫배열주소는 같음

     9     printf("%d %d \n", sizeof(count), sizeof(count[0][0]));

    10     printf("%d %p %p \n", count[0][0], &count[0][0], count);

    11

    12     // 행주소

    13     printf("%d \n" , sizeof(count[0]));

    14     printf("%p %p %p %p \n",

    15             count[0], count[1], count[2], count[3]);

    16

   

:!a.out

48 4

1 7ffff0e0 7ffff0e0

12

7ffff0e0 7ffff0ec 7ffff0f8 7ffff104

 

다음편에서는 본편에서 익힌 배열을 바탕으로 배열 포인터, 포인터 배열에 대하여 알아보겠습니다.


 

 

[고급 C++]C컴파일러와 C라이브러리(공유/정적/동적라이브러리)

[고급 C++]조건 컴파일 / make

[고급 C++]포인터 1편(프로세스/포인터변수/포인터연산/NULL포인터)

 

 

궁금한 사항은 댓글로 남겨주세요💃💨💫
좋아요와 구독(로그인X)은 힘이 됩니다 🙈🙉

 

반응형
그리드형

댓글

❤️김세인트가 사랑으로 키웁니다❤️