[C] 배열과 포인터의 관계

chiyongs·2021년 3월 21일
2
post-thumbnail

배열의 이름과 1차원 배열

int arr[] = {1,2,3,4,5};

// 배열이름 arr은 포인터이다.
// 함수의 인자로 배열을 1차원 배열을 전달하기 위해서는
// 파라미터를 아래와 같이 선언한다.

simpleMethod(int* arr) {
	...
}

배열 arr의 i번째 값은

  • arr[i]
  • *(arr+i)

두 가지 방식을 사용하여 접근할 수 있다.

문제!

int* arr[] = {a,b,c};

simpleMethod(???){
	...
}

simpleMethod에서 int* arr[]를 파라미터로 받고 싶을때 어떻게 선언해주어야 할까

  • 정답

    int* arr[] = {a,b,c};
    
    simpleMethod(int** arr) {
    	...
    }

2차원 배열

int main(void) {
	int arr2d[3][3];
	// arr2d는 주소 100에 선언되었다.
	
	//%p는 포인터 주소를 가리키는 형식, 16진수
	printf("%p \n", arr2d);    // ??
	printf("%p \n", arr2d[0]); // ??
	printf("%p \n", &(arr2d[0][0])); // ??

4바이트 -> 3= 12바이트 112
16진수 : 0~9,A,B,C,D,E,F // 100 + 16 = 110
	printf("%p \n", arr2d[1]); // ?? 10C C->12
	printf("%p \n", &(arr2d[1][0])); // ??

	//%lu는 부호가 없는 long형 출력, unsigned long 
	printf("size : %lu", sizeof(arr2d));    // 36
	printf("size : %lu", sizeof(arr2d[0])); // 12
	printf("size : %lu", sizeof(arr2d[1])); // 12
	printf("size : %lu", sizeof(arr2d[2])); // 12

	return 0;
} 
  • 정답

    100, 100, 100

    10c, 10c

    36, 12, 12, 12

그럼 포인터를 활용해보자

int main(void) {
	int apple[3][2];
	//apple은 주소 100에 선언되었다.
	int banana[2][3];
	//banana는 주소 500에 선언되었다.

	printf("%p \n", apple);   // 100
	printf("%p \n", apple+1); // 100 + 8
	printf("%p \n", apple+2); // 100 + 8 + 8 = 110
 
	printf("%p \n", banana);   // 500
	printf("%p \n", banana+1); // 500 + 12(c) = 50c
	printf("%p \n", banana+2); // 510 + 8 = 5 

	return 0;
}
  • 정답

    100, 108, 110

    500, 50c, 518

배열 포인터와 포인터 배열

  • 배열 포인터와 포인터 배열의 차이
int* dully[3];    // 포인터 배열 -> 배열을 선언한 것이다.
int (*dully)[3];  // 배열 포인터 -> 포인터를 선언한 것이다.
  1. 포인터 배열이란

배열의 요소가 포인터들로 이루어져 있다.

int* dully[3]; -> 배열 요소의 자료형이 int*인 배열, 요소의 갯수는 3char* dully[4]; -> 배열 요소의 자료형이 char*인 배열, 요소의 갯수는 4

동적할당을 이용하기

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void) {
    char* arr[3];
    char tmp[30];    //문자를 받을 char 배열 30자 까지만 받자
    unsigned long len;
    int i;
		
    for (i = 0; i < 3; i++)
    {
        printf("[%d] : ", i);
        scanf("%s", tmp);        //문자열 입력받기
        len = strlen(tmp) + 1;    //문자열 길이 + 1 할당 ('\0' 문자 포함)
        printf("[%d] : tmp \t주소 : %p\n", i, &tmp);    //tmp 주소 출력

        arr[i] = (char*)malloc(sizeof(char) * len);    //메모리 할당
        printf("[%d] : arr[%d]\t주소 : %p\n\n", i, i, &arr[i]);    //할당받은 arr[i] 메모리 주소 출력

        strcpy(arr[i], tmp);    //문자열을 arr[i]가 가리키고 있는 메모리로 복사
    }

    printf("\n");
    for (i = 0; i < 3; i++)
    {
        printf("arr[%d] = %s\t주소 : %p\n", i, arr[i], &arr[i]);
    }

    for (i = 0; i < 3; i++)
    {
        free(arr[i]);    //메모리 해제
    }
    return 0;
}

결과는??

주소로 나온 값을 유심히 살펴보자

  • 주소의 차이

    주소가 8만큼 차이 나는 이유는 바로 64비트 환경에서 작업하고 있기 때문이다. 많은 책에서 포인터의 크기는 4비트라고 하고 있지만 그건 32비트 환경일 때의 이야기이다.

  1. 배열 포인터란

→ 배열을 가리키는 포인터

→ 특정 사이즈의 배열만 가리킬 수 있는 "하나"의 포인터

팁🔥 특정 사이즈의 배열을 하나의 새로운 타입이라고 생각

크기가 다른 배열에 사용할 수 없음!!

선언방법

int (*ptr)[5]; //int 타입의 인덱스를 5개 가지고 있는 배열을 가리키는 포인터
int apple[5];
int bublle[5];
int wefaew[4];
char (*ptr)[3]; //char 타입의 인덱스를 3개 가지고 있는 배열을 가리키는 포인터
char aef[3] char bdfda[4]
// "타입이름 (*변수명)[N]

0개의 댓글