변수의 주소값
을 저장한다. * (참조연산자)
를 붙여서 선언합니다. #include <stdio.h>
int main()
{
int *p = NULL; // int* p == int * p 모두 같음
int num = 15;
p = #
// 포인터에 주소값을 넣을때는 * 연산자를 떼고 주소값을 넣어줌
printf("int 변수 num의 주소 : %d \n", &num);
printf("포인터 p의 값 : %d \n", p);
printf("포인터 p가 가리키는 값 : %d \n", *p);
return 0;
// 실행결과
// int 변수 num의 주소 : 22115228
// 포인터 p의 값 : 22115228
// 포인터 p가 가리키는 값 : 15
}
#include <stdio.h>
int main()
{
int *p = NULL;
int num = 15;
p = #
printf("포인터 p가 가리키는 값 : %d\n", *p);
printf("num의 값 : %d\n\n", num);
*p += 5;
printf("포인터 p가 가리키는 값 : %d\n", *p);
printf("num 값 : %d\n\n", num);
(*p)++;
printf("포인터 p가 가리키는 값 : %d\n", *p);
printf("num 값 : %d\n\n", num);
*p++;
printf("포인터 p가 가리키는 값 : %d\n", *p);
printf("num 값 : %d\n", num);
return 0;
// 실행 결과
//포인터 p가 가리키는 값 : 15
//num의 값 : 15
//포인터 p가 가리키는 값 : 20
//num 값 : 20
//포인터 p가 가리키는 값 : 21
//num 값 : 21
//포인터 p가 가리키는 값 : 572764048
//num 값 : 21
}
*p++
의 경우 주소를 먼저 찾아가지 않고 들어있는 변수 P
를 증가시키게 된다. 그러면 포인터 변수에 들어있는 주소값
이 증가하는 것인데, 증가한 그 주소에는 아무것도 선언되어 있지 않으므로 쓰레기값이 들어있습니다. 따라서 포인터 P
는 쓰레기값이 들어있는 주소를 가리키게 되는 것. 수정할 수 없다
는 뜻이죠.#include <stdio.h>
void pointerPlus(int *num)
{
*num += 5;
}
int main()
{
int num = 15;
printf("num 값 : %d\n", num);
pointerPlus(&num);
printf("함수 사용 후 : %d\n", num);
return 0;
}
// 실행결과
// num 값 : 15
//함수 사용 후 : 20
첫번째 요소의 주소값
을 나타낸다.#include <stdio.h>
int main()
{
int arr[5] = {10, 20, 30, 40, 50};
int *arrPtr = arr;
printf("%d\n", *arrPtr);
printf("%d\n", arr[0]);
return 0;
// 실행결과
// 10
// 10
}
++
,--
, +
,-
이 가능하며, 곱셈, 나눗셈 연산은 하지 못합니다.#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++);
printf("증가 연산 후 : %d %d\n", arrPtr, arrPtr2);
printf("변수 값 : %d %.2f\n", *arrPtr, *arrPtr2);
arrPtr += 2;
arrPtr2 += 2;
printf("증가 연산 후 : %d %d\n", arrPtr, arrPtr2);
printf("변수 값 : %d %.2f\n", *arrPtr, *arrPtr2);
return 0;
// 실행결과
// 포인터 주소 : 1617438912 1617438944
//증가 연산 후 : 1617438916 1617438952
//변수 값 : 20 20.20
//증가 연산 후 : 1617438924 1617438968
//변수 값 : 40 40.40
}
int
형 포인터인 arrPtr는 1을 더할때마다 4씩 증가하고, double
형 포인터인 arrPtr2는 8씩 증가합니다. (자료형의 크기) * N
만큼 증가한다는 것이죠. 감소 연산도 동일합니다.*(arr+i) == arr[i]
라는 것이다.i * (자료형의 크기)
만큼 더해지면 결국 배열 i 와 같아지는 것입니다.버블정렬
주어진 배열에서 첫번째 자료와 두번째 자료를, 두번째 자료와 세번째 자료, 세번째 자료와 네번째 자료.....(마지막-1) 번째 자료와 마지막 자료를 비교한 뒤 그 결과에 따라 값의 위치를 교환하며 정렬하는 방법을 말함.#include <stdio.h>
void bubbleSort(int len, int *arr)
{
int temp;
for(int i=0; i<len-1; i++)
{
for(int j=0; j<len-1-i; j++)
{
if(*(arr+j)>*(arr+j+1))
{
temp = *(arr+j);
*(arr+j) = *(arr+j+1);
*(arr+j+1) = temp;
}
}
}
}
int main()
{
int arr[10];
for(int i=0; i<10; i++)
{
scanf("%d", &arr[i]);
}
bubbleSort(10, arr);
for(int i=0; i<10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
const
를 붙여서 선언함#include <stdio.h>
int main()
{
int num = 10;
int *ptr1 = #
const int *ptr2 = #
*ptr1 = 20;
num = 30; //num자체가 상수가 된 것이 아니기때문에 오류가 나지 않았음
*ptr2 = 40; // 불가능
return 0;
}
// 실행결과
// 오류남
int* const ptr
과 같이 자료형 다음에 const
를 선언하게 되면 포인터 변수 자체가 상수화 됩니다. 주소값을 변경할 수 없다는 뜻이죠.*
연산자는 어디에 붙여주어도 상관없었습니다. 하지만 포인터를 상수화 시킬 때에는 const전에 *
연산자를 써주어야 합니다. #include <stdio.h>
int main()
{
int num1 = 10, num2 = 20;
int *ptr1 = &num1;
int* const ptr2 = &num1;
ptr1 = &num2;
*ptr2 = 30;
ptr2 = &num2; //불가능
return 0;
//실행결과
//오류
}
위와 같이 const
를 자료형 다음에 써주면, 포인터를 이용해서 값을 변경하는 것은 가능하지만 포인터가 가리키고 있는 주소값을 변경하는 것은 불가능합니다. 따라서
"이 포인터가 오로지 num1변수만을 가리키며, 절대 다른 변수를 가리키지 않겠다"
라고 생각한다면 위와 같이 써주면 되는 것입니다.
또한 포인터를 통해 값을 변경하는 것도, 다른 변수를 가리키는 것도 불가능하게 하고 싶다면,
아래와 같이 써주면 됩니다.
const inst* const ptr2 = #
#include <stdio.h>
int main()
{
int num = 10;
int *ptr;
int **pptr;
ptr = #
pptr = &ptr;
printf("num : %d, *ptr : %d, **ptr : %d\n", num, *ptr, **pptr);
printf("num 주소 : %d, ptr 값 : %d, **ptr 값 : %d\n", &num, ptr, *pptr);
printf("ptr 주소 : %d, pptr 값 : %d", &ptr, pptr);
return 0;
}
코드를 보시면 ptr
에는 num
의 주소값을 대입하고, pptr
에는 ptr
의 주소값을 대입했습니다. 참조 연산자를 사용하면 포인터가 가리키고 있는 변수의 값을 말한다고 설명했었습니다. 이중 포인터는 그 포인터가 가리키고 있는 곳으로 가서, 또 그 포인터가 가리키는 주소로 찾아가서 그 변수의 값을 사용합니다. 따라서 첫번째 출력문에서 num
의 주소인 &num
, 이 주소를 담고있는 ptr
의 값이 같습니다. 그리고 이중포인터는 참조 포인터를 두개 모두 쓰지 않고 하나만 쓸수도 있는데, 이렇게 되면 pptr
이 가리키고 있는 값을 의미합니다. 결국 ptr
변수에들어있는 값이 되겠죠. 그건 결국 num
의 주소값이니까, 세개의 값이 모두 같습니다.
포인터 배열
이라고 합니다. 어렵게 생각할 것은 없습니다. 그냥 일반 배열과 똑같은데, 포인터가 들어간다고 생각하면 됩니다. 어떻게 쓰는지 코드로 보도록 하겠습니다.#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]);
}
return 0;
//실행결과
//parr[0] : 10
//parr[1] : 20
//parr[2] : 30
}
참조 연산자를 붙인다는것만 빼면 일반 배열과 똑같이 선언하며, 대입할 때는 변수의 주소값을 넣습니다.
한 눈에 끝내는 c언어 기초 를 공부하고 작성한 글입니다.