포인터를 선언할 때 * 연산자가 둘 이상 사용되면 다중 포인터라 한다. *연산자는 얼마든지 사용될 수 있다.

 

다음과 같이 *연산자가 3개이상 삽입된 포인터 변수를 삼중 포인터 변수라고 한다. 

int ***tptr;

삼중 포인터 변수는 이중(더블) 포인터 변수를 가리키는(주소값을 저장하는) 용도로 사용된다.  

#include <stdio.h>

int main(void)
{
    int num = 100;
    int *ptr = &num;
    int **dptr = &ptr;
    int ***tptr = &dptr;

    printf("%d %d\n", **dptr, ***tptr);
    return 0;
}
// output : 100 100

위 코드는 삼중포인터의 선언과 접근에 대한 예시이다.

'Language > C, C++' 카테고리의 다른 글

[C] 함수 포인터  (0) 2021.01.08
[C] 2차원 배열의 포인터  (0) 2020.12.30
[C] 더블 포인터  (0) 2020.12.28
[C] 3차원 배열  (0) 2020.12.26
[C] 2차원 배열  (0) 2020.12.24

포인터 변수를 가리키는 또 다른 포인터 변수를 더블 포인터 또는 이중 포인터 라고 한다. 선언은 다음과 같이 * 연산자를 두 개 이어서 선언 한다.

int **dptr;

 

int main(void)
{
    double num = 3.14;
    double *ptr = &num;
    double **dptr = &ptr;
}

위와 같이 코드를 작성하게 되면 num 변수에는 3.14가 저장되어 있고, ptr변수는 num 변수의 주소를 가리키고 있고, dptr 변수는 ptr변수의 주소를 가리키고 있다. 또한 dptr 변수를 사용하여 다음과 같이 ptr변수와 num 변수에 접근할 수 있다. 

*dptr = ....;		// ptr 변수에 접근
*(*dptr) = ....;	// num 변수에 접근

*(*dptr)의 경우 괄호의 생략이 가능하여 **dptr로 접근할 수도 있다.

#include <stdio.h>

int main(void)
{
    double num = 3.14;
    double *ptr = &num;
    double **dptr = &ptr;
    double *ptr2;

    printf("%9p %9p\n", ptr, *dptr);
    printf("%9g %9g\n", num, **dptr);
    ptr2 = *dptr;   // ptr2 = ptr과 같음
    *ptr2 = 10.22;
    printf("%9g %9g\n", num, **dptr);
    return 0;
}
/* output : 
 0061FF10  0061FF10
     3.14      3.14
    10.22     10.22
*/

위와 같이 코드를 작성했을때 num 변수는 ptr변수와 ptr2변수가 가리키고 있고, ptr변수는 dptr변수가 가리키고 있다.

위와 같은 경우 변수 num에 접근하는 방법은 다음과 같다.

**dptr = 10.5;
*ptr = 10.5;
*ptr2 = 10.5;
num = 10.5;

위 4개의 경우 모두 num 변수에 10.5가 저장된다.

 

배열은 시작점의 주소를 가리키는 하나의 포인터이다. 포인터를 요소로 갖는 배열은 더블 포인터가 된다. 따라서 다음과 같이 포인터를 요소로 갖는 배열은 더블 포인터를 이용하려 접근할 수 있다.

#include <stdio.h>

int main(void)
{
    int num1 = 10, num2 = 20, num3 = 30;
    int *ptr1 = &num1;
    int *ptr2 = &num2;
    int *ptr3 = &num3;

    int *ptrArr[] = {ptr1, ptr2, ptr3};
    int **dptr = ptrArr;

    printf("%d %d %d\n", *(ptrArr[0]), *(ptrArr[1]), *(ptrArr[2]));
    printf("%d %d %d\n", *(dptr[0]), *(dptr[1]), *(dptr[2]));
    return 0;
}
/* output : 
10 20 30
10 20 30
*/

 

'Language > C, C++' 카테고리의 다른 글

[C] 2차원 배열의 포인터  (0) 2020.12.30
[C] 삼중 포인터  (0) 2020.12.28
[C] 3차원 배열  (0) 2020.12.26
[C] 2차원 배열  (0) 2020.12.24
[C] 포인터에서 const 사용  (0) 2020.12.20

const는 변수를 상수화 하기 위한 선언이다. 포인터 변수에도 const 선언이 가능하다.

#include <stdio.h>

int main(void)
{
    int num = 20;
    const int * ptr = &num;
    // *ptr = 30;   // 컴파일 에러
    num = 30;

    printf("test\n");
    return 0;
}

위 코드와 같이 const 선언한 포인터 변수가 가리키는 변수에 저장된 값을 변경하는 것은 허용되지 않는다. 그러나 num변수로 직접 값을 변경하는 것은 가능하다. 

다음 코드와 같이 const 선언은 포인터 변수의 이름 앞에 올 수 도 있다.

int * const ptr = &num;

위와 같이 변수 이름 앞에 const 선언을 했을 경우에는 주소 값의 변경이 불가능하다. 한 번 가리키기 시작한 변수를 끝까지 가리켜야 한다는 것이다. 가리키는 다음과 같이 가리키는 대상에 대한 저장된 값의 변경은 가능하다.

*ptr = 30;

다음과 같이 const선언을 하게 되면 주소값의 변경과, 가리키는 대상이 저장된 값 모두 변경이 불가능하다.

const int * const ptr = &num;

 

'Language > C, C++' 카테고리의 다른 글

[C] 3차원 배열  (0) 2020.12.26
[C] 2차원 배열  (0) 2020.12.24
[C] Call - by - value, Call - by - reference  (0) 2020.12.20
[C] 함수 인자로 배열 전달  (0) 2020.12.20
[C] 포인터 배열  (0) 2020.12.19

다음과 같이 포인터를 기반으로 문자열을 선언하는 것이 가능하다.

char *str = "My String";

이렇게 선언을 하면 메모리 공간에 "My String"이 저장되고, 문자열의 첫 번째 문자 M의 주소 값이 반환되어 포인터 변수 str에 저장된다. 배열로 선언한 문자열의 경우 계속해서 그 문자열을 가리키지만, 포인터로 선언한 문자열은 다음과 같이 다른 위치를 가리키도록 할 수 있다.

int main(void)
{
    char *str = "My String";
    str = "Your String";	// str이 가리키는 대상을 변경
}

배열로 선언된 문자열은 값의 변경이 가능하기 때문에 변수 형태의 문자열 이라 하고,  포인터로 선언된 문자열은 값이 변경이 불가능하여 상수 형태의 문자열 이라 한다.

 

#include <stdio.h>

int main(void)
{
    char str1[] = "My String";
    char *str2 = "Your String";
    printf("%s %s\n", str1, str2);

    str2 = "Our String";    // 가리키는 대상 변경
    printf("%s %s\n", str1, str2);

    str1[0] = 'X';      // 정상적으로 변경됨
    //str2[0] = 'X';    // 컴파일에서 에러 발생
    printf("%s %s\n", str1, str2);
    return 0;
}

위 코드와 같이 포인터로 선언한 문자열의 값을 변경하려 할때 컴파일이 정상적으로 안되는것을 확인할 수 있다.

 

'Language > C, C++' 카테고리의 다른 글

[C] 함수 인자로 배열 전달  (0) 2020.12.20
[C] 포인터 배열  (0) 2020.12.19
[C] 포인터 연산  (0) 2020.12.17
[C] 포인터와 배열  (0) 2020.12.17
[C] 포인터 변수  (0) 2020.12.16

포인터 변수를 대상으로도 증가 및 감소 연산이 가능하다.

#include <stdio.h>

int main(void)
{
    int * ptr1 = 0x0010;
    double * ptr2 = 0x0010;

    printf("%p %p\n", ptr1+1, ptr1+2);  // 4증가, 8증가
    printf("%p %p\n", ptr2+1, ptr2+2);  // 8증가, 16증가

    printf("%p %p\n", ptr1, ptr2);
    ptr1++;
    ptr2++;
    printf("%p %p\n", ptr1, ptr2);
    return 0;
}
/* output: 
00000014 00000018
00000018 00000020
00000010 00000010
00000014 00000018
*/

위 코드의 결과값을 보면 int형 포인터를 대상으로 1증가 시키면 4가 증가하고, double형 포인터를 대상으로 1증가시키면 8 이 증가한다. 포인터의 증감연산은 n 크기 만큼 증가 및 감소시 n x (자료형의 크기)만큼 주소값이 증가 및 감소함을 알 수 있다. 

 

포인터 연산을 활용하여 다음과 같이 배열의 요소에 접근할 수 있다.

int main(void)
{
    int arr[] = {1,2,3};
    int *ptr = arr;
    
    printf("%d\n", *(ptr+1));	// 2
    return 0;
}

 

'Language > C, C++' 카테고리의 다른 글

[C] 포인터 배열  (0) 2020.12.19
[C] 문자열 포인터  (0) 2020.12.18
[C] 포인터와 배열  (0) 2020.12.17
[C] 포인터 변수  (0) 2020.12.16
[C] 1차원 배열(2)  (0) 2020.12.14

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

#include <stdio.h>

int main(void)
{
    int arr[] = {0,1,2};
    printf("배열의 이름 : %p\n", arr);
    printf("첫 번째 요소 : %p\n",&arr[0]);
    printf("두 번째 요소 : %p\n",&arr[1]);
    printf("세 번째 요소 : %p\n",&arr[2]);
    return 0;
}
/* output : 
배열의 이름 : 0061FF14
첫 번째 요소 : 0061FF14
두 번째 요소 : 0061FF18
세 번째 요소 : 0061FF1C
*/

int형 배열의 요소간 주소 값의 차는 4바이트 인것을 확인할 수 있다. 또한 모든 배열 요소는 메모리 공간에 나란히 할당됨을 알 수 있다. 배열의 이름은 배열의 시작 주소 값을 의미하고, 그 형태는 값의 저장이 불가한 상수이다. 

 

배열의 이름도 포인터이기 때문에 배열의 이름을 피연산자로 하는  * 연산이 가능하다.

#include <stdio.h>

int main(void)
{
    int arr1[] = {1,2,3};
    double arr2[] = {1.1,2.2,3.3};

    printf("%d %g\n", *arr1, *arr2);
    *arr1 += 100;
    *arr2 += 120.5;
    printf("%d %g\n", *arr1, *arr2);
    return 0;
}
/* output: 
1 1.1
101 121.6
*/

배열의 이름이 가리키는 것은 배열의 첫번째 요소이기 때문에 배열의 이름을 대상으로 *연산을 하면 배열의 첫번째 요소에 접근된다.

 

#include <stdio.h>

int main(void)
{
    int arr[] = {10,20,30};
    int *ptr = &arr[0];

    printf("%d %d\n", ptr[0], arr[0]);
    printf("%d %d\n", ptr[1], arr[1]);
    printf("%d %d\n", ptr[2], arr[2]);
    return 0;
}
/* output : 
10 10
20 20
30 30
*/

위 코드와 같이 포인터를 배열의 이름처럼 사용할 수도 있다.

'Language > C, C++' 카테고리의 다른 글

[C] 문자열 포인터  (0) 2020.12.18
[C] 포인터 연산  (0) 2020.12.17
[C] 포인터 변수  (0) 2020.12.16
[C] 1차원 배열(2)  (0) 2020.12.14
[C] 1차원 배열(1)  (0) 2020.12.12

변수는 메모리 상에 저장되고, 포인터 변수는 메모리의 주소값을 저장하기 위한 변수이다.

#include <stdio.h>

int main(void)
{
    int num = 9;
    int *pNum;      // 포인터 변수 pNum 선언
    pNum = &num;    // pNum에 num의 주소값 저장

    printf("%d\n", pNum);   // 메모리 주소 출력
    printf("%d\n", *pNum);  // 메모리 주소에 저장된 값 출력

    *pNum = 20;     // pNum이 가리키는 주소에 저장된 값을 20으로 변경
    printf("%d\n", num);
    return 0;
}
/* output : 
6422296
9
20
*/

*으로 포인터 변수를 선언할 수 있고, &연산자는 피연산자의 주소값을 반환하는 연산자이다. &연산자의 피연산자는 변수여야 한다. 

*연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다. 

 

포인터 변수의 크기는 32비트 시스템에서는 주소값을 32비트로 표현하기에 4바이트이고, 64비트 시스템에선 주소값을 64비트로 표현하기 때문에 8바이트다.

'Language > C, C++' 카테고리의 다른 글

[C] 포인터 연산  (0) 2020.12.17
[C] 포인터와 배열  (0) 2020.12.17
[C] 1차원 배열(2)  (0) 2020.12.14
[C] 1차원 배열(1)  (0) 2020.12.12
[C] 재귀함수  (0) 2020.12.10

+ Recent posts