못정함

C언어) 9-1 포인터의 개념 본문

C언어 공부/C언어 독학 (교재)

C언어) 9-1 포인터의 개념

hadara 2024. 10. 9. 14:18

keyword

메모리 주소, &: 주소 연산자, *: 간접 참조 연산자


-C언어는 메모리에 접근해서 우리가 원하는 방식으로 데이터를 사용할 수 있게 해주는 언어이다.

-데이터에 접근하는 방식 : 변수 / 메모리 주소 값 (포인터 사용)

변수 선언된 블록{} 안에서만 사용
(함수 내부에서만 사용 가능)

-같은 변수명이어도 블록이나 함수가 다르면 별도의 저장공간을 확보하므로 전혀 다른 변수로 사용됨.

메모리 -사용 범위를 벗어난 경우에도 데이터를 공유할 수 있음


-메모리의 위치는 주소값으로식별 (바이트 단위로 구분)


 


<주소 연산자 &>

주소: 변수가 할당된 메모리 공간의 시작 주소

시작주소 위치부터 변수의 크기만큼 메모리를 사용함. 

*주소 출력하는 방법

#include <stdio.h>

int main(void)
{
    int a;
    double b;
    char c;

    printf("int address: %u\n", &a); //&는 주소 연산자
    printf("double address: %u\n", &b);
    printf("char address: %u\n", &c);
    
    return 0;
}

주소연산자 & : 단항 연산자 (시작주소만 return) 

&변수명

-주소는 보통 16진수로 표기함. 

-주소 출력 시 %p 사용하는 것이 좋음. 근데 난 바보니까 10진수로 출력하는 %u를 사용할 것임


<포인터와 간접 참조 연산자>

-한 번 구한 주소를 저장해서 사용하면 편하다

-포인터:변수의 메모리 주소를 저장하는 변수

포인터 선언

자료형 *변수명  (자료형은 주소 위치에 있는 변수의 자료형)
int *pa

* 는 포인터임을 표시하는 기호 

#include <stdio.h>

int main(void)
{
   int a; //일반 변수 선언
   int *pa; //포인터 선언

   pa = &a; // 포인터에 a의 주소를 대입 (저장)
   *pa = 10; // 포인터로 변수 a에 10을 대입 

   printf("pointer로 a값 출력: %d\n", *pa);
   printf("변수명으로 a값 출력: %d\n", a);    //변수 a값 출력

   return 0;
}

-포인터 변수 선언 이후에는 일반 변수처럼 변수명으로 사용가능.  (선언 시에는 *pa, 사용할 때는 pa)

- pa -> a : pa(포인터)가 a(변수)를 가리킨다. pa가 포인터이고 변수 a의 주소를 저장하고 있다는 뜻임.

 

간접 참조 연산자 * = 포인터 연산자

포인터가 어떤 변수를 가리키면 (=포인터가 변수의 주소를 저장하고 있으면)    가리키는 변수를 포인터로 사용할 수 있음

포인터 pa로 변수 a를 사용할 수 있음 (???????????????

a를 사용하려면 간접 참조 연산자 *를 사용해야함

*pa

*pa == a

포인터 pa가 a를 가리키므로 (포인터 pa가 a의 주소를 저장하고 있으므로)
*pa에 10을 대입하면
결국 a에 10을 대입한 것과 같다.



<여러가지 포인터 사용해보기>

-포인터가 어떤 변수를 가리키게 되면 그 이후엔 간접 참조 연산자(*)를 통해 가리키는 변수(a)를 자유롭게 쓸 수 있다.

*pa == a를 활용

#include <stdio.h>

int main(void)
{
    int a= 10, b=5, total;
    double avg;
    int *pa, *pb;  //포인터 동시 선언
    int *pt = &total;   //포인터 선언 + 초기화. total의 주소를 담음
    double *pg = &avg;  //포인터 선언 + 초기화. avg의 주소를 담음

    pa = &a; // pa에 a의 주소를 대입
    pb = &b; // pb에 b의 주소를 대입

    /*이제 모든 포인터가 변수를 가리킨다.*/

    *pt = *pa + *pb;    // *포인터 == 변수. 변수 값을 의미한다.
    *pg == *pt / 2.0; 

    printf("print value of a and b : %d, %d\n", *pa, *pb);   // 10, 15
    printf("print value of a + b: %d\n", *pt);    //25
    printf("avg: %.1lf\n", *pg);         //12.5

    return 0;


}

<const를 사용한 포인터>

const 예약어

변수에 사용 "변함없는" 이란 뜻으로, 값 변경 불가.

해당 변수를 상수 취급.
포인터에 사용 가리키는 변수의 값을 바꿀 수 없다는 의미 
(간접 참조해서 바꿀 수 없다)
#include <stdio.h>

int main(void)
{
    int a = 10, b = 20;
    const int *pa = &a;   // 포인터 pa는 a를 가리킨다.

    printf("value of a : %d\n", *pa);     // 10
    pa = &b;  //포인터가 변수 b를 가리키게 한다.
    printf("value of b: %d\n", *pa);      // 20
    pa = &a;  // 포인터가 다시 변수 a를 가리킨다.
    a = 30;   // a를 직접 참조해 값을 바꾼다.

    /* *pa = 30; 을 할 수 없음*/

    printf("value of a : %d\n", *pa);     // 20

    return 0;
}

const포인터 = pa가 가리키는 변수 a는 pa를 간접참조해서 바꿀 수 없다

변수 a 자체를 사용하면 얼마든지 바꾸기 가능.

*pa = 30; 안됨

a = 30; 됨

 

그럼 포인터에 const를 왜 쓰냐? ;;; -> 문자열 상수를 인수를 받는 함수에서 사용. (문자열 상수는 값이 바뀌면 안 되므로 함수의 매개변수를 통해 값을 바꿀 수 없도록, 매개변수로 선언된 포인터에 const를 사용함....뭐래는지 모르겠지만 12장에서 다시 배운다)

 


주소 연산자 int a;
&a;
간접 참조 연산자 *pa = 10; 

#include <stdio.h>

int main(void)
{
    int a= 10;
    int *p = &a;
    *p = 20;
    printf("%d", a);   //20

    return 0;
}