728x90

 

 

1. 포인터

더보기
#include <stdio.h>

void main()
{
    int iNum = 97;
    printf("   iNum 변수의 정수값: %d\n",  iNum);
    printf("   iNum 변수의 주소값: %p\n", &iNum);
    
    int *p_iNum = &iNum;
    printf(" p_iNum 포인터 변수값: %p\n", p_iNum);
    printf("*p_iNum 포인터 역참조: %d\n",*p_iNum);
}

/* 실행결과
   iNum 변수의 정수값: 97
   iNum 변수의 주소값: 0x7fffffffdd9c
 p_iNum 포인터 변수값: 0x7fffffffdd9c
*p_iNum 포인터 역참조: 97 */

 

2. 다차원 포인터

더보기
#include <stdio.h>
void main()
{
    int iNum = 90;
    printf("  iNum 변수의 정수값: %d\n", iNum);
    printf("  iNum 변수의 주소값: %p\n", &iNum);

    int *p_iNum = &iNum;
    printf("p_iNum 포인터 변수값: %p\n", p_iNum);

    int  *ptr1 =  p_iNum;  // 이건 됨
//  int  *ptr1 = &p_iNum;  // 이건 안됨


    // 포인터 변수가 저장된 공간의, 첫번째 바이트 주소값을  담으려면?
    int **ptr2 = &p_iNum;
    printf("   ptr 포인터 변수값: %p\n",   ptr2);
    printf("  *ptr 포인터 변수값: %p\n",  *ptr2);
    printf(" **ptr 포인터 변수값: %d\n", **ptr2);
}
/*   
  iNum 변수의 정수값: 90
  iNum 변수의 주소값: 0x7ffdefe9c374
p_iNum 포인터 변수값: 0x7ffdefe9c374
   ptr 포인터 변수값: 0x7ffdefe9c378 
  *ptr 포인터 변수값: 0x7fff8d7763a4
 **ptr 포인터 변수값: 90               */

 

 

3. 다차원 배열

더보기

3.1 배열 선언과 값 할당

:아래 1차원, 2차원, 3차원 모든 배열은, 값이 순차적으로 동일한 방식으로 저장된다.(!중요)

그러므로, 첫번째 바이트의 주소값만 알고 있다면, 모두 포인터 연산으로 접근 가능하다.

차이는, 다차원 배열의 문법적 사용법을 구분해 이해해야 한다.

#include <stdio.h>

int main(void)
{
    char cArr0[6]     = "ABCDEF";
    char cArr1[6]     = {1, 2, 3, 4, 5, 6};
    char cArr2[6]     = { 'A', 'B', 'C',   'D', 'E', 'F'};
    
    char cArr3[2][3]  = { 'A', 'B', 'C',   'D', 'E', 'F'};
    char cArr4[2][3]  = {{'A', 'B', 'C'}, {'D', 'E', 'F'}};
    char cArr5[3][2]  = {{'A', 'B'}, {'C', 'D'}, {'E', 'F'}};

    return 0;
}

 

 

 

 

3.2 1차원 배열의 순차 저장과 포인터 연산

배열명은, 메모리 주소값을 가진 숫자이므로, 산술연산이 가능하다.

#include <stdio.h>
 
int main(void)
{
    char cArr[6] = "ABCDEF";
    // char cArr[6] = {65, 66, 67, 68, 69, 70};
    // char cArr[6] = {'A', 'B', 'C', 'D', 'E', 'F'};

    printf(" cArr+0 : %p %c\n", cArr+0, *(cArr+0));
    printf(" cArr+1 : %p %c\n", cArr+1, *(cArr+1));
    printf(" cArr+2 : %p %c\n", cArr+2, *(cArr+2));
    printf(" cArr+3 : %p %c\n", cArr+3, *(cArr+3));
    printf(" cArr+4 : %p %c\n", cArr+4, *(cArr+4));
    printf(" cArr+5 : %p %c\n", cArr+5, *(cArr+5));
    printf("\n");
    
    return 0;
}

 

 

 

 

3.3 다차원 배열의 저장과 포인터 연산

다차원 배열은, 1차원 형태(크기)의 배열이 하나의 요소로 담겨있는 구조의 문법을 사용한다.

다차원 배열의 배열명(cArr2d)은, 포인터(cArr2d[0])가 아닌, 다중포인터(cArr2d)이다.

(1차원 배열명은 포인터이다. 포인터를 포인터 변수에 담으려면 다중 포인터 변수에 담아야한다.)

#include <stdio.h>
 
int main(void)
{  
    char cArr2D[2][3]  = {{'A', 'B', 'C'}, {'D', 'E', 'F'}};

    printf(" cArr2D+0 : %p %c\n", cArr2D+0);  // 0xAAB0 // +3byte char 배열[3] 크기만큼 증가
    printf(" cArr2D+1 : %p %c\n", cArr2D+1);  // 0xAAB3
    printf(" cArr2D+2 : %p %c\n", cArr2D+2);  // 0xAAB6
    printf(" cArr2D+3 : %p %c\n", cArr2D+3);  // 0xAAB9
    printf(" cArr2D+4 : %p %c\n", cArr2D+4);  // 0xAABC
    printf(" cArr2D+5 : %p %c\n", cArr2D+5);  // 0xAABF

    return 0;
}

 

 

 


3.4 프로그래밍 언어의 문법적 기호에는 모두 의미가 있다.

#include <stdio.h>
 
int main(void)
{
    // b. 배열의 할당과 내부 구조는 동일하다.
    char b1[6]    = { 'A', 'B', 'C',   'D', 'E', 'F'};
    char b2[2][3] = {{'A', 'B', 'C'}, {'D', 'E', 'F'}};

    printf("b2: %p, |   b2[0]: %p, |    b2[0][0]: %c\n", b2,   b2[0],    b2[0][0]);
    printf("b2: %p, |   b2[0]: %p, |  *(b2[0])  : %c\n", b2,   b2[0],  *(b2[0]));
    printf("b2: %p, | *(b2+0): %p, | **(b2+0)   : %c\n", b2, *(b2+0), **(b2+0));
    printf("\n");
    printf("b2: %p, |   b2[1]: %p, |    b2[1][0]: %c\n", b2,   b2[1],    b2[1][0]);
    printf("b2: %p, |   b2[1]: %p, |  *(b2[1])  : %c\n", b2,   b2[1],  *(b2[1]));
    printf("b2: %p, | *(b2+1): %p, | **(b2+1)   : %c\n", b2, *(b2+1), **(b2+1));
    printf("\n");
    printf("b2: %p, | (*b2)+1: %p, |*((*b2)+1)) : %c\n", b2, (*b2)+1, *((*b2)+1));
    printf("\n");

    return 0;
}

// 이중포인터           | 포인터                   | 값
// b2: 0x7ffc052686cc, |   b2[0]: 0x7ffc052686cc, |    b2[0][0]: A
// b2: 0x7ffc052686cc, |   b2[0]: 0x7ffc052686cc, |  *(b2[0])  : A
// b2: 0x7ffc052686cc, | *(b2+0): 0x7ffc052686cc, | **(b2+0)   : A

// b2: 0x7ffc052686cc, |   b2[1]: 0x7ffc052686cf, |    b2[1][0]: D
// b2: 0x7ffc052686cc, |   b2[1]: 0x7ffc052686cf, |  *(b2[1])  : D
// b2: 0x7ffc052686cc, | *(b2+1): 0x7ffc052686cf, | **(b2+1)   : D

// b2: 0x7ffc052686cc, | (*b2)+1: 0x7ffc052686cd, |*((*b2)+1)) : B

 

cArr       의미: 이중 포인터

cArr[ ]    의미: 포인터

cArr[ ][ ] 의미: 값

 

*(cArr + 0) 의미: 이중 포인터에 +0 연산(+3byte, 배열 행 크기만큼) 후, 이중포인터를 역참조하여 포인터 찾음.

(*cArr) + 0 의미: 이중포인터의 역참조하여 포인터를 찾고 +0 산술연산 

 


 

 

 

 

 

 

 

배열 첫번째 바이트 주소값을 포인터 변수에 담아서 사용해보기

#include <stdio.h>

int main(void)
{
    char arr[6]  = {'A', 'B', 'C', 'D', 'E', 'F'};

    char *ptr = arr;

    printf(" ptr+0 : %p %c\n", ptr+0, *ptr+0);
    printf(" ptr+1 : %p %c\n", ptr+1, *ptr+1);
    printf(" ptr+2 : %p %c\n", ptr+2, *ptr+2);
    printf(" ptr+3 : %p %c\n", ptr+3, *ptr+3);
    printf(" ptr+4 : %p %c\n", ptr+4, *ptr+4);
    printf(" ptr+5 : %p %c\n", ptr+5, *ptr+5);

    return 0;
}

 

 

 

 

#include <stdio.h>
 
int main(void)
{
    char arr3D[2][2][3] = {
        {
            {'A', 'B', 'C'},
            {'D', 'E', 'F'}
        },
        {
            {'G', 'H', 'I'},
            {'J', 'K', 'L'}
        }
    };
    //(void *) 생략
    
    // Layer 0
    printf("┌─────────────────── 3D 배열 구조 ────────────────────────┐\n");
    printf("│     arr3D         : %p\n",         arr3D                          );
    printf("│     arr3D[0]      : %p\n",         arr3D[0]                       );
    printf("│     arr3D[0][0]   : %p\n",         arr3D[0][0]                    );
    printf("│     arr3D[0][0][0]: %p -> %c\n", &(arr3D[0][0][0]), arr3D[0][0][0]);
    printf("├─────────────────────────────────────────────────────────┤\n");
    printf("│     arr3D         : %p\n",            arr3D           );
    printf("│   *(arr3D + 0)    : %p\n",          *(arr3D+0)        );
    printf("│  **(arr3D + 0)    : %p\n",        *(*(arr3D+0))       );
    printf("│ ***(arr3D + 0)    : %p -> %c\n", &(***(arr3D+0)), ***(arr3D+0));
    printf("└─────────────────────────────────────────────────────────┘\n\n");

    
    // Layer 1
    printf("┌─────────────────── 3D 배열 구조 ────────────────────────┐\n");
    printf("│     arr3D         : %p\n",         arr3D                          );
    printf("│     arr3D[1]      : %p\n",         arr3D[1]                       );
    printf("│     arr3D[1][0]   : %p\n",         arr3D[1][0]                    );
    printf("│     arr3D[1][0][0]: %p -> %c\n", &(arr3D[1][0][0]), arr3D[1][0][0]);
    printf("├─────────────────────────────────────────────────────────┤\n");
    printf("│     arr3D         : %p\n",            arr3D           );
    printf("│   *(arr3D + 1)    : %p\n",          *(arr3D+1)        );
    printf("│  **(arr3D + 1)    : %p\n",        *(*(arr3D+1))       );
    printf("│ ***(arr3D + 1)    : %p -> %c\n", &(***(arr3D+1)), ***(arr3D+1));
    printf("└─────────────────────────────────────────────────────────┘\n\n");


    // Layer 2
    printf("┌─────────────────── 3D 배열 구조 ────────────────────────┐\n");
    printf("│     arr3D         : %p\n",         arr3D                          );
    printf("│     arr3D[1]      : %p\n",         arr3D[1]                       );
    printf("│     arr3D[1][1]   : %p\n",         arr3D[1][1]                    );
    printf("│     arr3D[1][1][0]: %p -> %c\n", &(arr3D[1][1][0]), arr3D[1][1][0]);
    printf("├─────────────────────────────────────────────────────────┤\n");
    printf("│     arr3D         : %p\n",            arr3D);
    printf("│   *(arr3D + 1)    : %p\n",          *(arr3D+1));
    printf("│  *(*arr3D) + 1)   : %p\n",        *((*arr3D)+1));
    printf("│ **(*arr3D) + 1)   : %p -> %c\n", &(**((*arr3D)+1)), **(*arr3D)+1);
    printf("└─────────────────────────────────────────────────────────┘\n\n");
 
    return 0;
}

 


4. 함수와 다차원 배열

더보기
#include <stdio.h>

int main(void)
{
    int arr_2d[4][4] = {
        0,
    };

    //1
    unsigned char ucSize = sizeof(arr_2d);  // arr_2d 메모리 크기 Byte
    unsigned char ucRow = sizeof(*arr_2d);  // arr_2d[0] 1차원 크기 Byte
    unsigned char ucCol = ucSize/ucRow; // arr_2d 메모리 크기 전체를 1차원 크기로 나누면 컬럼 개수

    printf("%d %d %d\n", ucSize, ucRow, ucCol);

    //2
    printf("  arr_2d: %p %2d\n",   arr_2d, sizeof(arr_2d));   //arr_2d[0][0] 의 포인터의 포인터
    printf(" *arr_2d: %p %2d\n",  *arr_2d, sizeof(*arr_2d));  //arr_2d[0][0] 의 포인터
    printf("**arr_2d: %d %2d\n", **arr_2d, sizeof(**arr_2d)); //arr_2d[0][0]

    return 0;
}

 

#include <stdio.h>

int change_Arr_2d(int *arr)
{
    printf("%p\n", arr);
    printf("입력하세요 >> ");
    scanf("%d", arr + 0); // arr[0]
    printf("입력하세요 >> ");
    scanf("%d", arr + 1); // arr[1]
    printf("입력하세요 >> ");
    scanf("%d", arr + 2); // arr[2]
    printf("입력하세요 >> ");
    scanf("%d", arr + 3); // arr[3]

    return 0;
}

int print_Arr_2d(int *arr_2d)
{
    unsigned char ucSize = sizeof(arr_2d);
    unsigned char ucRow = sizeof(*arr_2d);
    unsigned char ucCol = ucSize/ucRow;

    printf("%d %d %d\n", ucSize, ucRow, ucCol);

    unsigned char cnt = 0;

    for (size_t i = 0; i < 4; i++)
    {
        for (size_t j = 0; j < 4; j++)
        {
            printf("%d ", *(arr_2d+cnt));
            // printf("%d ", (*arr_2d)[j]);
            cnt+=1;
        }
        printf("\n");
    }

    return 0;
}

int main(void)
{
    int arr_2d[4][4] = {
        0,
    };

    //3
    int *ptr = &(arr_2d[0][0]);

    change_Arr_2d(*arr_2d);
    
    //4
    // print_Arr_2d(*arr_2d);
    print_Arr_2d(ptr);

    return 0;
}