공부했던 자료 정리하는 용도입니다.

재배포, 수정하지 마세요.

 

 


 포인터 

  1. 포인터
    • 포인터 변수
    • 포인터 변수의 선언
      * 포인터 변수의 크기
    • 포인터 형(type)
    • 포인터 변수와 관련된 연산자
      1. & 연산자
      2. * 연산자
    • null 포인터
    • 포인터 대상의 const 선언
      * 상수를 가리키는 포인터인 경우
      * 포인터 자체가 상수인 경우
      * 포인터가 상수이면서 상수를 가리키는 경우
  2. 포인터와 배열
    • 포인터 연산
    • 문자열의 선언방식
    • 포인터 배열
      * 문자열 배열
  3. 포인터와 함수
    • 함수의 호출 방식
      * Call-by-value
      * Call-by-reference
    • 함수의 인자로 배열 전달
      * 인자로 배열 전달 시 배열의 크기
  4. 이중 포인터(더블 포인터)
    • 이중 포인터 선언과 사용
    • 포인터 변수 대상의 Call-by-reference
    • 포인터 배열과 포인터 배열의 포인터 type
    • 다중 포인터 변수
  5. 다차원 배열과 포인터
    • 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
    • 2차원 배열의 증감 연산
    • 2차원 배열의 포인터
    • 함수 인자로 2차원 배열 전달
    • 다차원 배열에서 arr[i]와 *(arr + i)
    • 배열 포인터와 포인터 배열
    • main 함수의 인자
      * 인자의 형성 과정
      * char * argv[ ]
  6. 함수 포인터
    • 함수 포인터 변수 선언
  7. void 포인터

 


 

포인터와 배열

  배열도 포인터이다. 그러나 값을 바꿀 수 없는 '상수 형태의 포인터'이다.

 

 

포인터 연산

arr[i] == *(arr + i);

  ``type``형 포인터를 대상으로 ``n``의 크기만큼 값을 변경시키면 @@n × sizeof(type)@@의 크기만큼 주소 값이 증가/감소한다.(``int``형일 경우 ``4``씩, ``double``형일 경우 ``8``..) 그래서 위와 같이 배열일 경우 @@arr[i] == *(arr + i)@@이 성립한다.

 

 

 

 

문자열의 선언방식

   마지막에 null 문자가 삽입되는 문자열의 선언방식 

  1. 변수 형태의 문자열 : 배열 이용
  2. 상수 형태의 문자열 : ``char``형 포인터 변수 이용

 

//마지막에 null 문자가 삽입되는 문자열의 선언방식 
// 1. char형 배열 이용(변수 형태의 문자열,  문자열 변경 가능)
char str1[] = "String1";

// 2. char형 포인터 변수 이용(상수 형태의 문자열, 문자열 변경 불가)
char * str2 = "String2";

  ``str1``은 그 자체로 문자열 전체를 저장하는 배열이다. ``str2`` 처럼 선언하면 메모리 공간에 문자열 ``String``이 저장되고, 문자열의 첫 번째 문자 ``S``의 주소 값이 반환된다. 그리고 그 반환 값이 포인터 변수 ``str2``에 저장된다. ``str1``, ``str2`` 모두 문자열의 시작 주소 값을 가리키고 있다는 것에서는 동일하지만 ``str1``은 상수 형태의 포인터이기 때문에 가리키는 대상을 변경할 수 없는 반면, ``str2``는 가리키는 대상을 변경할 수 있다.  배열로 선언되는 문자열을 '변수 형태의 문자열'이라 하고 ``char``형 포인터 변수를 이용해서 선언한 문자열은 '상수 형태의 문자열'이라고 한다. 

 

  ##"##로 묶여서 표현되는 문자열은 그 형태에 상관없이 메모리 공간에 저장된 후 그 주소 값이 반환된다. 그래서 ##printf## 함수는 문자열이 아닌 문자열의 주소 값을 전달받는 함수이다. (인자가 ##char *## 형)

 

 

 

 

포인터 배열

#include <stdio.h>

int main(void)
{
	int num1 = 10, num2 = 20, num3 = 30;
	int * arr[3] = {&num1, &num2, &num3};
	
	printf("%d \n", *arr[0]);
	printf("%d \n", *arr[1]);
	printf("%d \n", *arr[2]);
	
	return 0;
}

포인터 변수로 이뤄져 주소 값의 저장이 가능한 배열을 포인터 배열이라고 한다.

 

 

 

  ■ 문자열 배열

#include <stdio.h>

int main(void)
{
	char * strArr[3] = {"Simple", "String", "Array"};
	
	printf("%s \n", strArr[0]);
	printf("%s \n", strArr[1]);
	printf("%s \n", strArr[2]);
	
	return 0;
}

  문자열 배열은 문자열의 주소 값을 저장할 수 있는 배열로서 사실상 ``char *``형 포인터 배열이다. ``"``로 묶여서 표현되는 문자열은 메모리 공간에 저장된 후, 주소 값이 반환되므로 실제로는 ``strArr``에 각 문자열의 주소 값들이 들어있는 것이다. 

 

 

 

 

 


포인터와 함수

함수의 호출 방식

 

   함수의 호출 방식 

  • Call-by-value : 을 전달하는 형태의 함수 호출
  • Call-by-reference : 주소 값을 전달하는 형태의 함수 호출

 

  ■ Call-by-value

#include <stdio.h>

void Swap(int n1, int n2)
{
	int temp = n1;
	n1 = n2;
	n2 = temp;
	printf("n1 n2 : %d %d \n", n1, n2);
}

int main(void)
{
	int num1 = 10;
	int num2 = 20;
	printf("num1 num2 : %d %d \n", num1, num2);
	
	Swap(num1, num2);
	printf("num1 num2 : %d %d \n", num1, num2);
	
	return 0;
}

함수 호출 시 전달되는 인자의 값은 매개변수에 복사가 되는데 이런 방식을 Call-by-value라고 한다.

그래서 위의 예시의 경우 ``Swap``함수를 호출해서 ``main``함수의 ``num1``과 ``num2``값을 서로 바꾸려 했지만 바뀌지 않았다.

 

실행 결과

 

 

 

  ■ Call-by-reference

#include <stdio.h>

void Swap(int * n1, int * n2)	// 매개변수의 주소값을 인자로 받음
{
	int temp = *n1;
	*n1 = *n2;
	*n2 = temp;
}

int main(void)
{
	int num1 = 10;
	int num2 = 20;
	printf("num1 num2 : %d %d \n", num1, num2);
	
	Swap(&num1, &num2);	// 매개변수가 포인터이므로 주소값 전달
	printf("num1 num2 : %d %d \n", num1, num2);
	
	return 0;
}

앞의 예시에서 함수로 실제 변수값을 바꾸고 싶다면 변수의 주소 값을 인자로 받아서 처리해야 된다.

이런 방식을 Call-by-reference라고 한다.

 

실행 결과

 

 

 

 

함수의 인자로 배열 전달

void ShowArayElem(int * param, int len) {...}
void AddArayElem(int * param, int len, int add) {...}

// 배열의 주소값이 인자로 전달될 때에는 주로 아래와 같이 선언된다.
void ShowArayElem(int param[], int len) {...}
void AddArayElem(int param[], int len, int add) {...}

  함수의 매개변수로 배열을 선언할 수 없지만 배열의 주소 값을 전달하는 것은 가능하다. 일반적으로 배열의 주소 값이 인자로 전달될 때에는 배열인 것을 강조하기 위해 ``param[ ]``과 같은 표현을 더 많이 사용한다. (매개 변수일 때만 서로 변환 가능)

 

int arr[3] = {1, 2, 3};
int * ptr = arr;	//int ptr[] = arr;로 대체 불가능

매개변수가 아닌 경우에는 대체할 수 없다.

 

 

 

  ■ 인자로 배열 전달 시 배열의 크기

#include <stdio.h>

void ShowArayElem(int * param, int len)
{
	for(int i = 0 ; i < len ; i++)
		printf("%d ", param[i]);
	printf("\n");
}

int main(void)
{
	int arr1[3] = {1, 2, 3};
	int arr2[5] = {4, 5, 6, 7, 8};
	ShowArayElem(arr1, sizeof(arr1) / sizeof(int));
	ShowArayElem(arr2, sizeof(arr2) / sizeof(int));
	
	return 0;
}

  배열의 주소 값을 인자로 전달받는 매개변수는 포인터 변수이기 때문에 이를 대상으로 ``sizeof``연산을 할 경우 배열의 크기가 아닌 포인터 변수의 크기가 반환된다. 따라서 배열의 크기를 알 수 없기 때문에 배열의 크기나 길이 정보도 함께 인자로 전달해야 한다.

 

 

 

'기타 > C' 카테고리의 다른 글

[C] 다차원 배열과 포인터  (0) 2020.05.19
[C]이중 포인터(더블 포인터)  (0) 2020.05.12
[C] 포인터  (0) 2020.05.05
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열)  (1) 2020.04.28
[C] 함수  (0) 2020.04.27

+ Recent posts