포인터 개념
// 실행할떄마다 주소가 변경됨
// 영희네와 민수네 주소를 잘 알아냈다.
// 포인터 변수는 int/ char/ double 상관없이 주소값을 알고 있는 변수에 찾아가서 값도 직접 바꿀 수 있고 메모리 공간의 주소도 알아낼 수 있다.
이를 통해서 포인터 변수라는 것은 포인터 즉, 어떤 변수의 주소값을 가지는 포인터 자체가 그 변수의 값을 직접 바꿀 수 있다. 라고 알 수 있다.
그렇다면 미션맨의 주소는?
별로 멀리살지 않는다
포인터와 배열
#include <stdio.h>
int main(void)
{
int arr[3]={5, 10, 15};
int *ptr=arr;
for(int i=0; i<3; i++)
{
printf("배열 arr[%d]의 값: %d\n", i, arr[i]);
}
for(int i=0;i<3; i++)
{
printf("포인터 ptr[%d]의 값: %d\n", i, ptr[i]);
}
return 0;
}
난 이거 결과를 포인터의 값 아래 3개는 주소가 나올 거라고 예상했는데...웬 걸...?
왜 값이 똑같이 나오지...?
포인터라는 녀석은 배열이 가리키고 있는 이 값들, 즉 배열 하나하나의 주소 값을 그대로 가지고 있는 것이다.
똑같이 접속을 해서 값을 가지고 온 것이다.
#include <stdio.h>
int main(void)
{
int arr[3]={5, 10, 15};
int *ptr=arr;
for(int i=0; i<3; i++)
{
printf("배열 arr[%d]의 값: %d\n", i, arr[i]);
}
for(int i=0;i<3; i++)
{
printf("포인터 ptr[%d]의 값: %d\n", i, ptr[i]);
}
ptr[0]=100;
ptr[1]=200;
ptr[2]=300;
for(int i=0;i<3; i++)
{
printf("포인터 ptr[%d]의 값: %d\n", i, ptr[i]);
}
for(int i=0; i<3; i++)
{
printf("배열 arr[%d]의 값: %d\n", i, arr[i]);
}
return 0; }
결과 포인터 자체 값과 배열 자체 값 또한 바뀌었다.
그렇다는 것은 포인터라는 녀석이 각각 배열 요소에 그대로 가서 값을 바꾸고 있었다.
즉, 이는 ptr과 arr이 똑같은 녀석이라고 볼 수 있다.
printf("배열 arr[%d]의 값: %d\n", i, *(arr+i));
printf("배열 ptr[%d]의 값: %d\n", i, *(ptr+i)");
이렇게 표현하면 arr이라는 것 자체는 arr배열이 처음 시작되는 주소 값을 가지고 있다. 그 주소로부터 i번쨰 해당하는 녀석의 값을 가져오는 것이라서 이렇게 사용할 수 있다. 그리고 지금 작성된 이 문법은
printf("배열 arr[%d]의 값: %d\n", i, arr[i]);
printf("배열 ptr[%d]의 값: %d\n", i, ptr[i]);
이 문법과 완전이 똑같은 개념이다.
즉!!
*(arr+i) == arr[i] 와 똑같은 표현
arr은 arr배열의 첫 번쨰 값의 주소와 동일하다.
즉 "arr == arr[0]"
#include <stdio.h>
int main(void)
{
int arr[3]={5, 10, 15};
int *ptr=arr;
printf("arr 자체의 값: %d\n",arr);
printf("arr 자체의 값: %d\n", &arr[0]);
return 0;}
?????????
arr변수명을 치면 5가 나올 줄 알았는데....
주소값이 나왔다.
#include <stdio.h>
int main(void)
{
int arr[3]={5, 10, 15};
/* int *ptr=arr; */
printf("arr 자체의 값: %d\n",arr);
//printf("arr 자체의 값: %d\n", &arr[0]);
return 0;}
이래도
그냥 arr이라고 하면 주소 자체를 나타내는 것이라고 명심해야 한다.
arr[숫자] => 값이 나옴
arr==&arr[숫자] => 주소가 나옴
포인터가 arr이라는 자체 값을 가지면 첫번쨰 주소의 값을 가지는 것
int main(void)
{
int arr[3]={5, 10, 15};
printf("arr 자체의 값이 가지는 주소의 실제 값: %d\n", *arr);
return 0;
}
이러면 값이
5가 나온다
arr라는 이 자체 값을 주소를 가진다. 그 주소가 가지고 있는 실제 값을 찍어보는 것이다.
그래서 앞에 *을 붙였다.
즉 arr==주소, *arr==값
printf("arr[0]의 실제 값: %d\n", *arr[0]);
이러면 오류가 발생한다.
수정하자.
#include <stdio.h>
int main(void)
{
int arr[3]={5, 10, 15};
printf("arr 자체의 값이 가지는 주소의 실제 값: %d\n", *arr); // *(arr+0)과 같은 의미
printf("arr[0]의 실제 값: %d\n", *&arr[0]); //
return 0;
}
이러면
이러한 결과가 나온다.
*&가 같이 있다는 의미는 앰퍼센트부터 해석해보자면, 이 변수의 주소의 값을 나타내는 것이라서 둘이 있으면아무것도 없는 것과 같다.
&는 주소이며, *는 그 주소의 값을 의미하는 것이라서 *&이렇게 붙어 있으면 상쇄가 된다.
#include <stdio.h>
int main(void)
{
int i=0;
printf("%d\n", &i);
printf("%d\n", *&i);
return 0;
}
배열처럼 일반변수도 마찬가지 결과
SWAP
#include <stdio.h>
void swap(int a, int b);
int main(void)
{
int a=10;
int b=20;
// a와 b의 값을 바꾼다.
printf("swqp함수 전에는 -> a: %d, b: %d\n", a, b);
swap(a,b);
printf("swap함수 후에는 -> a: %d, b: %d\n", a, b);
return 0;
}
void swap(int a, int b)
{
int temp=a;
a=b;
b=temp;
}
이미 배웟던 거지만..함수에서만 원하는 결과가 호출될 수 있다.
void swap(int a, int b)
{
int temp=a;
a=b;
b=temp;
printf("swap함수 후에는 -> a: %d, b: %d\n", a, b);
}
대학교 다닐떄 이거 정말 이해하기 어려웠는데 머리가 크고 생각해보면
이런 구조
우리가 이를 값의 의한 복사라고 하는데(Call by value)
main함수 안에 a의 주소와 b의 주소를 확인해보자.
#include <stdio.h>
void swap(int a, int b);
int main(void)
{
int a=10;
int b=20;
// a와 b의 값을 바꾼다.
printf("a의 주소 값: %d\n",&a);
printf("b의 주소 값: %d\n",&b);
//printf("swqp함수 전에는 -> a: %d, b: %d\n", a, b);
swap(a,b);
//printf("swap함수 후에는 -> a: %d, b: %d\n", a, b);
return 0;
}
void swap(int a, int b)
{
int temp=a;
a=b;
b=temp;
//printf("swap함수 후에는 -> a: %d, b: %d\n", a, b);
printf("(swap함수 내)a의 주소 값: %d\n",&a);
printf("(swap함수 내)b의 주소 값: %d\n",&b);
printf("(swap함수 내)temp의 주소 값: %d\n", &temp);}
결과가 의외였다.
난 함수를 호출해도 그 이전과 같은 주소 값이 나올 줄 알았는데, 함수 내부의 a, b는 서로 다른 값이었다.
그렇다면 메모리 공간에 있는 주소값을 넘기게 되면 어떻게 될까???
#include <stdio.h>
void swap(int a, int b);
void swap_addr(int *a, int *b);
int main(void)
{
int a=10;
int b=20;
// a와 b의 값을 바꾼다.
printf("a의 주소 값: %d\n",&a);
printf("b의 주소 값: %d\n",&b);
printf("swqp함수 전에는 -> a: %d, b: %d\n", a, b);
swap(a,b);
printf("swap함수 후에는 -> a: %d, b: %d\n", a, b);
printf("a의 주소 값: %d\n",&a);
printf("b의 주소 값: %d\n",&b);
printf("swqp함수 전에는 -> a: %d, b: %d\n", a, b);
swap_addr(&a,&b); //주소를 넘기는 거니까 a의 &를 붙여서 넘기고, 주소는 포인터변수를 선언
printf("swap함수 후에는 -> a: %d, b: %d\n", a, b);
return 0;
}
void swap(int a, int b)
{
int temp=a;
a=b;
b=temp;
printf("swap함수 후에는 -> a: %d, b: %d\n", a, b);
printf("(swap함수 내)a의 주소 값: %d\n",&a);
printf("(swap함수 내)b의 주소 값: %d\n",&b);
printf("(swap함수 내)temp의 주소 값: %d\n", &temp);
}
void swap_addr(int *a, int *b) //*a로 해서 주소값을 넘긴다.
{
int temp=*a; //a는 주소 값을 가지는 거니까 실제 값인 *을 붙여서 집어넣고
*a=*b; //a의 값에도 b의 값을 집어넣도록
*b=temp; //b의 값에도 temp를 집어넣도록 처리한다.
printf("swap함수 후에는 -> a: %d, b: %d\n", a, b);
printf("(주소값 전달)SWAP함수 내 -> a:%d, b:%d\n", *a, *b);
}
일일이 다 적어놓았으니 코드는 다시 리뷰하고 설명해보자면
주소값을 전달하기 전에는 a는 10, b는 20이었는데, 주소 값 전달하고 나서 a는 20, b는 10으로 변경되었다.
주소 값을 전달해서 그들이 가진 값을 바꾼 것