[C] 포인터와 배열 및 실습 [박은종 쌤의 포인터 강의]
Programming/C language

[C] 포인터와 배열 및 실습 [박은종 쌤의 포인터 강의]

목차

C언어 포인터 / 박은종 쌤의 포인터 강의 3~5

- 포인터와 배열 - 1

- 포인터와 배열 실습 - 1

- 포인터와 배열 실습 - 2

 


C언어 포인터 / 박은종 쌤의 포인터 강의

포인터와 배열 - 1

https://www.youtube.com/watch?v=ce37lzsbUgQ&t=333s 

 포인터를 왜 쓰는가? 

- 메모리의 주소를 가지면 항상 접근 가능

- 매개 변수로 전달하기 편함

- 배열이나 구조체와 함께 쓰면 아주 편리함

 

int arr[5]

0 ~ n-1 인덱스 생성

 

 배열의 가장 큰 장점은 인덱스 연산이 가능하다는 점, element를 찾는 속도가 정말 빠르다. 산술 연산으로 계산하기 때문에, 빅-오 표기법으로 O(1)에 해당한다.

 그에 반해, 링크드 리스트는 논리적으로는 다음 것으로 예상 가능하지만, 물리적으로 걸리는 시간은 모든 개수를 다 찾아야 하기 때문에 오래 걸리며, 빅-오 O(n)에 해당한다.

 

 배열의 이름은 주소이다. 포인터에 배열의 이름을 assign 하면 포인터로 접근 가능하다.

 


포인터와 배열 실습 - 1

https://www.youtube.com/watch?v=2FyplQq4EPI 

 배열

- 동일한 자료형을 일렬로 관리하는 선형 자료구조

- 물리적 위치와 논리적 위치가 동일함

- 배열의 이름은 주소다

- 배열은 인덱스 연산을 할 수 있다

 

배열의 각각의 요소 값들의 주소 값을 아래 실습을 통해 알아보자.

gcc로 컴파일 후  a.out로 확인해보면 아래처럼 4바이트씩 할당되어있는 것을 알 수 있다.

int형 arr이기 때문에 각각의 요소 값 하나씩 모두 4바이트로 할당된다.

 

포인터와 배열

- 배열의 이름은 배열의 시작 주소

- 배열의 이름은 값을 바꿀 수 없는 '상수 형태의 포인터'

 

int a[5];

int *pa;

pa = &a[0];

pa = a;

 

위처럼 선언을 했을 때, 아래 사진과 같이 할당되는 상태인 것이다.

 

 

포인터 연산

- 포인터는 연산하거나 비교할 수 있음

- 연산은 정수와의 덧셈, 뺄셈만 가능

- 포인터 변수 간의 연산은 뺄셈만 가능

- 배열과 함께 사용할 때 증/감 연산을 많이 사용

 

포인터 변수 + 정수 : pa +1; pa++; ++pa;

포인터 변수  - 정수 : pa -2; pa--; --pa;

포인터 변수 포인터 변수

pa1과 pa2 두 개의 변수가 동일한 배열을 가리킬 때

i = p2 - pa1 // 두 변수가 가리키는 요소의 간격

 

포인터 연산은 더하기는 되지 않고 오로지 뺄셈만 가능하다.

간격의 크기인 2가 출력되는 모습

포인터와 배열

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

int *pa = array;

 

실습 코드

 아래의 사진을 보면 포인터가 배열에 어떻게 접근하는지 직관적으로 이해할 수 있다. *(pa + i), i++ 형태로 접근하면 pa가 가리키고 있는 주소를 늘려 접근하지만, pa가 가리키고 있는 주소는 봐뀌지 않는다.

 

 그 이유는 대입 연산자를 사용하지 않아, 기존에 가리키고 있던 주소 값은 변하지 않기 때문이다.

 

 반면 대입 연산자(증감 연산자) *(pa++)을 사용을 하면 해당 주소 값이 계속 변화하게 된다.

 

 


포인터와 배열 실습 - 2

https://www.youtube.com/watch?v=wHgh_HftTFI 

 

*pa++과 *(pa + 1)은 다름

연산 후 pa++ 은 연산 후 포인터의 위치가 이동함

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

int *pa1 = a;

int *pa2 = a;

 

*(++pa1) = 10;

*(pa2 + 2) = 20;

 

 

포인터와 배열 실습

int main(void)

{
   int array[5] = {10, 20, 30, 40, 50};

   int *ptr = array;

  

   printf("++*ptr = %d\n", ++*ptr);

   printf("*++ptr = %d\n", *++ptr);

   printf("--*ptr = %d\n", --*ptr);

   printf("*--ptr = %d\n", *--ptr);

   printf("*(ptr++) = %d\n", *(ptr++));

   printf("*(ptr--) = %d\n", *(ptr--));

 

   return 0;

}

 

결과 값

int array[5] = {10, 20, 30, 40, 50}

int *ptr = array

 

++*ptr 의 의미는 포인터가 현재 가리키고 있는 값을 1 증가시키는 것이다, 전위 연산자이기 때문에 statement가 끝나기 전에 연산이 되어 버린다. 현재 *ptr이 가리키고 있는 것은 배열의 시작점인 10이다. 그렇기 때문에 연산이 되어 11이 출력된다.

 

*++ptr의 의미는 ptr 포인터의 위치를 한 칸 대입 연산하여 옮긴 값을 출력하는 것이다. 현재 0번 인덱스에서 1 증가시킨 1번 인덱스 값을 출력하게 된다.

 

--*ptr의 의미는 포인터가 현재 가리키는 값을 -1 하여 값을 변경시킨다. 그렇기에 현재 가리키고 있는 값이 20 - 1 되어 19가 된다.

 

*--ptr의 의미는 포인터의 위치를 대입 연산하여 한 칸 이전으로 간다. 즉 현재 0번 인덱스 값을 출력하게 되는 것. (현재 11이다)

 

*(ptr++)의 의미는 현재 가리키고 있는 값을 출력하고 나서 후위 연산되어 포인터의 위치가 증가하게 하는 것이다.

 

*(ptr--)의 의미는 현재 가리키고 있는 값을 출력하고 나서 후위 연산되어 포인터의 위치가 한 칸 감소하게 되는 것이다.

 

 

문자열

문자열을 표현하는 방법

 

char pstr1[] = "hello";  // 배열

char *pstr2 = "hello";  // 문자열 상수

 

배열의 값은 변경 가능하다.

문자열은 상수다. 문자열은 불변(immutable)이다.

 

실습 코드