#정리
# printf - 주소출력
// printf로 값을 출력할 때는 타입에 맞게 형식을 쓰며, 주소를 출력할 때는 %p를 이용한다.
- value : %d, %c, %s, %lld, %f, %lf, %c, %s - address : %p
//배열 변수는 실제 값이 아닌, 값의 시작 주소를 가진다.
- printf("sus[0] address : %p\n", &sus[0]);//index를 주면 실제 값을 가진다.
- printf("sus address : %p\n", sus);//배열의 시작 주소는 sus[0]의 시작 주소와 같다.
- printf("sus[0] value : %d\n", sus[0]);//index를 주면 실제 값을 가진다.
//문자열 배열도 주소값을 가지지만, 문자열 배열은 %s로 바로 출력이 가능하다.
- printf("cs value : %s\n", cs);
# pointer : 참조 변수
(1. 주소값 반환 및 역참조 값 출력)
//& : 주소를 표현하는 연산자
- su : 값 / &su : su값의 메모리 주소
//* : 포인터 - 참조형 연산자로 주소값을 담을 수 있는 변수 타입을 만들 수 있다.
- ** 주소값을 담는 그릇이지, 포인터 변수가 주소값은 아니다. (4.변수로써의 포인터 내용 참조)**
//참조 연산자 포인터(*)를 사용할 때는 변수 본래의 타입과 맞춰줘야한다.
//변수 주소를 포인터 변수에 할당하는 것을 통해 포인터 변수를 초기화 한다.
- int *pt = &su;
//포인터 변수에 참조 연산자를 붙이면 해당 주소의 값이 나온다.
- printf("*pt : %d\n",*pt);//값의 용량이 커지면, 주소로 보내는 쪽이 효율이 좋아진다.
- 주소는 4Byte로 용량이 일정하기 때문.
(2. 값 변경 및 역참조 변경)
//변수 선언 이후, 초기화(값 지정)가 없으면 경고가 뜨지만, 변수는 인정해준다.
- 대신 변수에는 알 수 없는 값이 들어가고, 주소는 임의의 주소가 들어간다.
//변수의 값을 바꿔도 변수 주소는 바뀌진 않는다.
//포인터변수를 역참조한 값을 다른 변수에 넣으면 값은 같아도 다른 변수이므로, 주소가 달라진다.
//특정 변수의 주소 값을 역참조하여 안에 있는 값을 바꾸면, 대상 변수의 값도 같이 바뀐다.
- 하지만 동일 값을 가진 다른 변수의 값과 주소에는 영향이 없다.
(3. 상수처리 효과)
//포인터 변수에 const 처리를 하면 기본적으로 값을 변경할 수 없지만, 다른 값이 있는 주소값으로 변수 값을 변경하여 우회하여 역참조로 출력되는 값을 변경할 수 있다.
- *p_total = *p_kor + *p_eng + *p_math; //const read-only error : 주소 내부에 있는 값을 변경할 수 없다.
- const int* p_total = &total; >> p_total = &kor;//국어 값이 들어있는 주소로 바뀜 >>const(상수)일때, 값 자체는 변경이 안되지만 주소를 변경하는 것을 통해 값을 변경할 수 있는 여지가 있다.
(4. 변수로써의 포인터)
//포인터 변수도 주소를 담는 "변수"이기 때문에, 값을 바꿔서 넣을 수 있다.
** null 값으로도 변수를 초기화 할 수 있다. >> (nil) **
- 선언 후 초기화 하지않으면, 쓰레기(임의의 주소) 값이 들어간다.
- 다른 변수들의 주소 값으로 변경 가능하다.
//동적 메모리 할당이 매번 해제되고, 다시 할당되면서 동일한 메모리 주소값을 부여받은 사례
- test01( ), test02( ), test03( )에서 받아온 배열 값의 메모리 주소가 모두 같은 것을 볼 수 있다.
# printf - 주소출력
// printf로 값을 출력할 때는 타입에 맞게 형식을 쓰며, 주소를 출력할 때는 %p를 이용한다.
- value : %d, %c, %s, %lld, %f, %lf, %c, %s
- address : %p
//배열 변수는 실제 값이 아닌, 값의 시작 주소를 가진다.
- printf("sus[0] address : %p\n", &sus[0]);//index를 주면 실제 값을 가진다.
- printf("sus address : %p\n", sus);//배열의 시작 주소는 sus[0]의 시작 주소와 같다.
- printf("sus[0] value : %d\n", sus[0]);//index를 주면 실제 값을 가진다.
//문자열 배열도 주소값을 가지지만, 문자열 배열은 %s로 바로 출력이 가능하다.
- printf("cs value : %s\n", cs);
--예문 코드 보기--
#include <stdio.h>
int main(int argc, char **argv)
{
printf("pointer...\n");
//printf로 출력할 때 사용되는 타입
//>> value : %d, %c, %s, %lld, %f, %lf, %c, %s
//>> address : %p
printf("----------- int -----------------\n");
int su = 100;
printf("su value : %d\n", su);
printf("su address : %p\n", &su);
printf("------------- long ---------------\n");
long lsu = 3000;
printf("lsu value : %ld\n", lsu);
printf("lsu address : %p\n", &lsu);
printf("------------ double ----------------\n");
double d = 3.14;
printf("d value : %lf\n", d);
printf("d address : %p\n", &d);
printf("-------------- number array --------------\n");
int sus[4] = {11,22,33,44}; //배열 변수는 실제로 갑을 가지고 있지 않고, 값의 주소를 가진다.
printf("sus[0] value : %d\n", sus[0]);//index를 주면 실제 값을 가진다.
printf("sus[0] address : %p\n", &sus[0]);//index를 주면 실제 값을 가진다.
printf("sus address : %p\n", sus);//배열의 시작 주소는 sus[0]의 시작 주소와 같다.
printf("-------------- character --------------\n");
char c = 'A';
printf("c value : %c, %d\n",c,c);
printf("c address : %p\n", &c);
printf("-------------- char array --------------\n");
char cs[4] = {'a','b','c','\0'};
printf("c[0] value : %c, %d\n", cs[0], cs[0]);
printf("c[0] address : %p\n", &cs[0]);
printf("cs address : %p\n", cs);
printf("cs value : %s\n", cs);//문자열 배열도 주소값을 가지지만, 문자 배열은 %s로 바로 출력이 가능하다.
return 0;
}
# pointer : 참조 변수 - 1. 주소값 반환 및 역참조 값 출력
//& : 주소를 표현하는 연산자
- su : 값 / &su : su값의 메모리 주소
//* : 포인터 - 참조형 연산자로 주소값을 담을 수 있는 변수 타입을 만들 수 있다.
- ** 주소값을 담는 그릇이지, 포인터 변수가 주소값은 아니다.**
//참조 연산자 포인터(*)를 사용할 때는 변수 본래의 타입과 맞춰줘야한다.
//변수 주소를 포인터 변수에 할당하는 것을 통해 포인터 변수를 초기화 한다.
- int *pt = &su;
//포인터 변수에 참조 연산자를 붙이면 해당 주소의 값이 나온다.
- printf("*pt : %d\n",*pt);
//값의 용량이 커지면, 주소로 보내는 쪽이 효율이 좋아진다.
- 주소는 4Byte로 용량이 일정하기 때문.
--예문 코드 보기--
#include <stdio.h>
void test01(int *pt);
void test02(double *pt2);
void test03(char *pt3);
int main(int argc, char **argv)
{
printf("pointer...\n");
printf("---- int - test01 -----\n");
int su = 100;
printf("su : %d\n",su);
printf("&su : %p\n",&su);//address operator
printf("---- int - test01 -----\n");
//참조 연산자 포인터(*)를 사용할 때는 변수 본래의 타입과 맞춰줘야한다.
int *pt = &su; //su변수 주소를 포인터 변수에 할당해줘.
printf("pt : %p\n",pt);//할당된 su의 메모리 주소값이 출력된다.
printf("*pt : %d\n",*pt);//포인터 변수에 참조 연산자를 붙이면 해당 주소의 값이 나온다.
test01(&su);
//double test02 mission
printf("---- double - test02 -----\n");
double su2 = 3.14;
printf("su2 : %lf\n",su2);
printf("&su2 : %p\n",&su2);
printf("---- double - test02 -----\n");
double *pt2 = &su2;
printf("pt : %p\n",pt2);
printf("*pt : %lf\n",*pt2);
test02(&su2);
//char test03 mission
printf("---- char - test03 -----\n");
char abc = 'A';
printf("abc : %c\n",abc);
printf("&abc : %p\n",&abc);
printf("---- char - test03 -----\n");
char *pt3 = &abc;
printf("pt : %p\n",pt3);
printf("*pt : %c\n",*pt3);
test03(&abc);
return 0;
}//end main()
void test01(int *pt){
printf("---- int - test01 -----\n");
//값의 용량이 커지면, 주소로 보내는 쪽이 효율이 좋아진다.
printf("test01...pt : %p\n",pt);
printf("test01...*pt : %d\n",*pt);
}
void test02(double *pt2){
printf("---- double - test02 -----\n");
printf("test02...pt2 : %p\n",pt2);
printf("test02...*pt2 : %lf\n",*pt2);
}
void test03(char *pt3){
printf("---- char - test03 -----\n");
printf("test03...pt3 : %p\n",pt3);
printf("test03...*pt3 : %c\n",*pt3);
}
# pointer : 참조 변수 - 2. 값 변경 및 역참조 변경
//변수 선언 이후, 초기화(값 지정)가 없으면 경고가 뜨지만, 변수는 인정해준다.
- 대신 변수에는 알 수 없는 값이 들어가고, 주소는 임의의 주소가 들어간다.
//변수의 값을 바꿔도 변수 주소는 바뀌진 않는다.
//포인터변수를 역참조한 값을 다른 변수에 넣으면 값은 같아도 다른 변수이므로, 주소가 달라진다.
//특정 변수의 주소 값을 역참조하여 안에 있는 값을 바꾸면, 대상 변수의 값도 같이 바뀐다.
- 하지만 동일 값을 가진 다른 변수의 값과 주소에는 영향이 없다.
--예문 코드 보기--
#include <stdio.h>
int main(int argc, char **argv)
{
printf("pointer...\n");
printf("----- int pointer -----\n");
//변수 선언
int su;
int *pt;
//초기화가 없으면 경고가 뜨지만, 변수는 인정해준다.
//>> 알 수 없는 값과 임의의 주소가 들어간다.
printf("su: %d\n",su);
printf("pt: %p\n",pt);
printf("----- var init -----\n");
//변수 초기화
su = 100;
pt = &su;
printf("su: %d\n",su);
printf("pt: %p\n",pt);
printf("----- var value change -----\n");
//변수에 대한 주소이므로, 변수의 값을 바꿔도 주소가 바뀌진 않는다.
su = 1000;
printf("su: %d\n",su);
printf("pt: %p\n",pt);
printf("----- different var init -----\n");
//포인터변수를 역참조한 값을 변수x에 넣으면 값은 같지만 다른 변수이므로, 주소가 달라진다.
int x = *pt;
printf("x: %d\n",x);
printf("&X: %p\n",&x);
printf("----- dereference var change -----\n");
//해당 주소의 값을 역참조로 바꾸면, 해당 변수(su)의 값도 같이 바뀐다.
//하지만 변수(x)의 값과 주소에는 영향이 없다.
*pt = 10000;
printf("su: %d\n",su);
printf("pt: %p\n",pt);
printf("*pt: %d\n",*pt);
printf("x: %d\n",x);
printf("&X: %p\n",&x);
//double pointer mission
printf("====== double pointer =======\n");
double d;
double* pt_d;
d = 3.1415;
pt_d = &d;
printf("su: %lf\n",d);
printf("pt_d: %p\n",pt_d);
d = 6.789;
printf("su: %lf\n",d);
printf("pt_d: %p\n",pt_d);
double e = *pt_d;
printf("e: %lf\n",e);
printf("&e: %p\n",&e);
*pt_d = 12.345;
printf("d: %lf\n",d);
printf("pt_d: %p\n",pt_d);
printf("*pt_d: %lf\n",*pt_d);
printf("e: %lf\n",e);
printf("&e: %p\n",&e);
//char pointer mission
printf("====== char pointer =======\n");
char c;
char* pt_c;
c = 'A';
pt_c = &c;
printf("c: %c\n",c);
printf("pt_c: %p\n",pt_c);
c = 'B';
printf("c: %c\n",c);
printf("pt_c: %p\n",pt_c);
char abc = *pt_c;
printf("abc: %c\n",abc);
printf("&abc: %p\n",&abc);
*pt_c = 'C';
printf("c: %c\n",c);
printf("pt_c: %p\n",pt_c);
printf("*pt_c: %c\n",*pt_c);
printf("abc: %c\n",abc);
printf("&abc: %p\n",&abc);
return 0;
}
# pointer : 참조 변수 - 3. 상수처리 효과
//포인터 변수에 const 처리를 하면 기본적으로 값을 변경할 수 없지만, 다른 값이 있는 주소값으로 변수 값을 변경하여 우회하여 역참조로 출력되는 값을 변경할 수 있다.
- *p_total = *p_kor + *p_eng + *p_math; //const read-only error : 주소 내부에 있는 값을 변경할 수 없다.
- const int* p_total = &total; >> p_total = &kor; //국어 값이 들어있는 주소로 바뀜 >>const(상수)일때, 값 자체는 변경이 안되지만 주소를 변경하는 것을 통해 값을 변경할 수 있는 여지가 있다.
--예문 코드 보기--
#include <stdio.h>
int main(int argc, char **argv)
{
printf("pointer...\n");
int kor=99, eng=88, math=77;
const int total = kor + eng + math;
//total = 300;//const read-only error (상수 변경 시도 에러)
double avg = 0.00;
printf("%d %d %d %d %.2lf\n",kor,eng,math,total,avg);
int* p_kor = &kor;
int* p_eng = ŋ
int* p_math = &math;
const int* p_total = &total;
//p_total = &kor; //국어 값이 들어있는 주소로 바뀜 >>const(상수)일때, 값 자체는 변경이 안되지만 주소를 변경하는 것을 통해 값을 변경할 수 있는 여지가 있다.
double* p_avg = &avg;
//*p_total = *p_kor + *p_eng + *p_math; //const read-only error
*p_avg = total/3.0;
printf("%d %d %d %d %.2lf\n",*p_kor,*p_eng,*p_math,*p_total,*p_avg);
printf("----mission---\n");
int a = 10;
int b = 20;
int c = 30;
int sum = 0;
double avg2 = 0.00;
printf("%d %d %d %d %.2lf\n",a,b,c,sum,avg2);
int *p_a = &a;
int *p_b = &b;
int *p_c = &c;
int *p_sum = ∑
double *p_avg2 = &avg2;
*p_sum = *p_a+*p_b+*p_c+*p_sum;
*p_avg2 = *p_sum/3;
printf("%d %d %d %d %.2lf\n",*p_a,*p_b,*p_c,*p_sum,*p_avg2);
return 0;
}
# pointer : 참조 변수 - 4. 변수로써의 포인터
//포인터 변수도 주소를 담는 "변수"이기 때문에, 값을 바꿔서 넣을 수 있다.
** null 값으로도 변수를 초기화 할 수 있다. >> (nil) **
- 선언 후 초기화 하지않으면, 쓰레기(임의의 주소) 값이 들어간다.
- 다른 변수들의 주소 값으로 변경 가능하다.
//동적 메모리 할당이 매번 해제되고, 다시 할당되면서 동일한 메모리 주소값을 부여받은 사례
- test01( ), test02( ), test03( )에서 받아온 배열 값의 메모리 주소가 모두 같은 것을 볼 수 있다.
--예문 코드 보기--
#include <stdio.h>
#include <stdlib.h>
int *test01();
double *test02();
char *test03();
int main(int argc, char **argv)
{
printf("pointer...\n");
//int *pt;
//printf("pt: %p\n",pt);//경고: 쓰레기 주소 값이 들어감.
int *pt = NULL;
printf("pt(null): %p\n",pt); //>>(nil) - 주소값을 null로 초기화 할 수 있다.
//포인터 변수는 주소를 담는 변수이기 때문에, 값을 바꿔서 넣을 수 있다.
int su = 100;
pt = &su;
printf("pt(su): %p\n",pt);//input su's address
printf("*pt(su): %d\n",*pt);//su's value
int kor = 99;
pt = &kor;
printf("pt(kor): %p\n",pt);//input kor's address
printf("*pt(su): %d\n",*pt);//kor's value
printf("-----------\n");
pt = test01();
printf("pt(test01): %p\n",pt);
printf("*pt(test01): %d\n",*pt);
free(pt);
printf("-----------\n");
double *pt_d = test02();
printf("pt(test02): %p\n",pt_d);
printf("*pt(test02): %.2lf\n",*pt_d);
free(pt_d);
printf("-----------\n");
char *pt_c = test03();
printf("pt(test03): %p\n",pt_c);
printf("*pt(test03): %c\n",*pt_c);
free(pt_c);
return 0;
}
int *test01(){
int su01 = 11;
int* p_su01 = malloc(sizeof(int));//동적 메모리 할당을 하면, 메모리가 사라지지 않는다.
*p_su01 =su01;
return p_su01;
//return &su01;//메모리가 사라지면서 받아올 때 쓰레기 값이 나온다.
}
double *test02(){
double* p_d02 = malloc(sizeof(double));
*p_d02 =3.14;
return p_d02;
}
char *test03(){
char* p_c03 = malloc(sizeof(double));
*p_c03 ='A';
return p_c03;
}