개념
변수의 주소값 저장
int *p=NULL; //*의 위치는 상관 없음 int* p, int * p모두 가능
int num=15
p=#
포인터 변수의 크기는 모두 동일하다. 자료형으로 선언하는 이유는 가리키는 주소의 값이 어떤 자료형을 가지는지를 알려주기 위해서이다.
참조 연산자9
참조 연산자(*)는 포인터나 주소의 앞에 사용하며 포인터가 가리키는 주소에 저장된 값을 반환
int *p = NULL;
int num = 15;
p = #
printf("포인터 p값 num값 : %d %d\n", *p); //15 15
*p += 5;
printf("포인터 p값 num값 : %d %d\n", *p); //20 20
(*p)++;
printf("포인터 p값 num값 : %d %d\n", *p); //21 21
*p++;
printf("포인터 p값 : %d\n", *p); //쓰레기 값
//증감 연산자 ++,--가 참조연산자 *보다 우선순위가 높기때문에 주소가 이동되버림
printf("num 값 : %d\n", num); //21
함수에서의 포인터
메인 함수에서 포인터를 선언하지 않아도 된다.
void pointerPlus(int *num)
{*num += 5;}
void numPlus(int num)
{num += 5; }
int main()
{
int num = 15;
printf("num 값 : %d\n", num);
numPlus(num); //call-by-value
pointerPlus(&num); //call-by-reference
위의 코드에서 numPlus 함수는 값을 복사해서 넘기기 때문에 num의 값이 바뀌지 않는다. 이처럼 값을 복사하여 넘겨주는 것을 call-by-value라 한다.
pointerPlus 함수는 주소값을 넘겨주기 때문에 num의 값이 20으로 바뀐다. 이처럼 주소값을 그대로 넘겨주는 것을 call-by-reference라 한다.
※ 엄밀히 따지면 c언어는 주소값을 복사하여 넘겨주기 때문에 call-by-value의 종류인 call-by-address를 사용한다.
그렇지만 결과적으로는 call-by-reference의 역할을 수행하기 때문에 그렇게 봐도 무방하지 않을까..?
포인터 연산
#include <stdio.h>
int main()
{
int arr[5] = {10, 20, 30, 40, 50};
double arr2[5] = {10.1, 20.2, 30.3, 40.4, 50.5};
int *arrPtr = arr;
double *arrPtr2 = arr2;
printf("포인터 주소 : %d %d\n", arrPtr++, arrPtr2++); //임의로 a b라 한다.
printf("증가 연산 후 : %d %d\n", arrPtr, arrPtr2); // a+4 , b+8
printf("변수 값 : %d %.2f\n", *arrPtr, *arrPtr2); // 20 20.20
arrPtr += 2;
arrPtr2 += 2;
printf("증가 연산 후 : %d %d\n", arrPtr, arrPtr2); //a+4+(2*4) b+8+(2*8)
printf("변수 값 : %d %.2f\n", *arrPtr, *arrPtr2); // 40 40.4
return 0;
}
*(arr+i) == arr[i]
상수 포인터
c언어에서 상수 포인터는 3종류가 있다.
1.포인터가 가리키는 값이 상수일 경우 (const int*p)
int a = 10, b = 20;
const int *p = &a; // 포인터가 가리키는 값이 변경 불가능
printf("%d\n", *p); // 출력: 10
// *p = 20; 오류! 값을 변경할 수 없음
p = &b; // OK! 포인터가 다른 변수를 가리키는 것은 가능
printf("%d\n", *p); // 출력: 20
2. 포인터가 상수일 경우 ( int *const p)
int a = 10, b = 20;
int *const p = &a; // 포인터 자체가 변경 불가능
printf("%d\n", *p); // 출력: 10
*p = 20; // OK! 값 변경 가능
// p = &b; 오류! 포인터 자체를 변경할 수 없음
printf("%d\n", *p); // 출력: 20
3. 포인터와 가리키는 값 모두 상수일 경우 (const int *const p)
int a = 10, b = 20;
const int *const p = &a; // 포인터도 변경 불가능, 값도 변경 불가능
printf("%d\n", *p); // 출력: 10
// *p = 20; // 오류! 값 변경 불가능
// p = &b; // 오류! 포인터 변경 불가능
이중포인터
int num=10;
int *ptr; //num의 주소를 가리키는 포인터 ptr 선언
int **pptr; // ptr의 주소를 가리키는 이중포인터 pptr 선언
포인터 배열
#include <stdio.h>
int main()
{
int num1 = 10, num2 = 20, num3 = 30;
int *parr[3]; // 배열의 값으로 주소가 들어간다.
parr[0] = &num1;
parr[1] = &num2;
parr[2] = &num3;
for(int i=0; i<3; i++)
{
printf("parr[%d] : %d\n", i, *parr[i]); // 10 20 30 출력
}
return 0;
}

