#include <stdio.h>
void swap(int*, int*);
void func_point(int, int);
int main(void)
{
/* 단순한 형태의 포인터 */
/*
int a = 0;
int* pa = &a;
int** ppa = &pa;
printf("a : %d \n", a);
printf("&a : %p \n\n", &a);
printf("pa : %p \n", pa); // 포인터 변수 pa에 저장된 주소 값 => &a
printf("*pa : %d \n", *pa); // 포인터 변수 pa에 저장된 주소에 접근하여 그 주소가 가리키는 값을 가져와라
printf("&pa : %p \n\n", &pa); // 포인터 변수 pa의 주소 값
printf("ppa : %p \n", ppa); // 포인터 변수 ppa에 저장된 주소 값 => 포인터 변수 pa의 주소 값 &pa
printf("*ppa : %p \n", *ppa); // 포인터 변수 ppa에 저장된 주소(&pa)에 접근하여 값을 가져와라(&a)
printf("**ppa : %d \n", **ppa); // 포인터 변수 ppa에 저장된 포인터 변수(pa)가 가리키는 값을 가져와라(a)
printf("&ppa : %p \n\n", &ppa); // 포인터 변수 ppa의 주소 값
*/
/* 배열 포인터 */
//int arr[] = { 1,2,3,4,5 };
//int arr2[] = { 6,7,8,9,10 };
//int* parr = arr;
//printf("%p\n", arr);
//printf("%p\n", parr);
//printf("%d\n", parr[0]); //
//printf("%d\n", *(parr+0)); // 아래와 같은 의미
//printf("%d\n", *(parr)); // 위와 같은 의미
//parr[0] = 3; // 변수형태의 문자열 값 변경 가능
//printf("%d\n", parr[0]);
//parr = arr2; // 포인터 변수 변경 가능
//printf("%d \n", parr[0]);
/* 상수 형태의 문자열 포인터 */
//char* str = "hi man fuxx you"; // 메모리상에 자동으로 저장된 문자열 hi man fuxx you의 첫 번째 문자를 단순히 가리키고만 있음
//printf("%c \n", *str); // 서식문자를 %c로 지정한 이유는 위에 적었듯이 문자열의 첫 번째 문자를 가리키고 있기 때문에 그 주소 값에 접근하여 값을 가져오게 함
//printf("%s \n", str); // 문자열 출력
//printf("%p \n", str); // 문자열의 첫번째 주소 메모리 주소 출력
//printf("%c \n", str[0]); // 문자열의 첫 번째 요소에 접근해서 값을 가져와라
//printf("%c \n", *(str+0)); //위와 같은 의미 주소 값 + 1
//str = "No thanks"; // 포인터 변수 변경 가능
//printf("%s\n", str);
//
////str[0] = "O"; // 상수형태의 문자열 값 변경 불가
////printf("%s\n", str);
/* 변수 형태의 문자열 포인터*/
/*char var_arr[] = "boring pointer";
for (int i = 0; i < sizeof(var_arr) / sizeof(char); i++)
printf("%c", var_arr[i]);
printf("\n");
char* p_arr = var_arr;
printf("var_arr[0] : %c \n", var_arr[0]);
printf("*(var_arr+0) : %c \n", *(var_arr+0));
printf("p_arr[0] : %c \n", p_arr[0]);
printf("*(p_arr+0) : %c \n", *(p_arr+0));*/
/* 포인터 배열 */
/*int num1 = 1;
int num2 = 2;
int num3 = 3;
int* arr[] = { &num1, &num2, &num3 };
int** parr = arr; // 주소값을 가르키는 배열이기 때문에 더블 포인터
printf("*arr[0] : %d \n", *arr[0]);
printf("*(*(arr+0)) : %d \n\n", *(*(arr+0)));
printf("parr : %p \n", parr);
printf("arr : %p \n\n", arr);
printf("*parr[0] : %d \n ", *parr[0]);
printf("*(*(parr+0)) : %d \n\n ", *(*(parr+0)));
*/
/* 다차원 배열 포인터 */
//int arr2[][4] = { 1,2,3,4,5,6,7,8 };
//int(*parr)[4] = arr2; // int형을 가리키고, 포인터 연산 시 sizeof(int) x 4의 크기로 값이 변화는 포인터 변수
//for (int i = 0; i < 2; i++)
// printf("%d %d %d %d \n", parr[i][0], parr[i][1], parr[i][2], parr[i][3]);
//printf("&(arr2[0][0]) : %p\n", &(arr2[0][0]));
//printf("&(arr2) : %p\n", &(arr2));
//printf("parr : %p\n", parr);
//printf("parr+1 : %p\n", parr + 1);
//printf("arr2[1][0] : %p \n", &(arr2[1][0]));
//printf("*(*(parr+0)) : %d\n", *(*(parr + 0)));
/* Call by reference */
//int n1 = 1;
//int n2 = 2;
//printf("%d %d \n", n1, n2);
//printf("swap!\n");
//swap(&n1, &n2);
//printf("%d %d \n", n1, n2);
/* 함수 포인터*/
//int num1 = 0;
//int num2 = 10;
//void (*func_pointer)(int, int) = func_point;
//func_pointer(num1, num2);
}
void swap(int* ptr1, int* ptr2)
{
int temp = *ptr1;
*ptr1 = *ptr2;
*ptr2 = temp;
}
void func_point(int n1, int n2)
{
printf("%d %d = %d", n1, n2, n1 + n2);
}