2016년 11월 28일 월요일

[C language] C언어 기본 문법_2

[차례]

6. 포인터
 -포인터 이해
 -포인터와 배열
 -포인터와 함수
 -다중 포인터
-다차원 배열과 포인터
-함수 포인터


[6. 포인터]


[6-1 이해]
선언: 
ex) int num = 7;
    int * pnum;
    int pnum = $num; //num의 주소 값을 반환한다.
    int pnum2 = 0;     //주소 값 0을 저장하는 것이 아닌 아무데도 가리키지 않음.
- int type 변수면 포인터변수도 int type이여야 한다.

[오류]



[6-2 포인터와 배열]

-배열은 상수 형태의 포인터
ex)     int arr1[]={1,2,3};
double arr2[]={1.1, 2.2, 3,3};

printf("%d %g \n",*arr1,*arr2); // 1, 1.1
*arr1+=100;
*arr2+=200.5;
printf("%d %f \n",*arr1,*arr2); //101, 201.6
int * parr = &arr1[2];
printf("%d\n",*parr); //3
-arr[i] == *(arr+i)  //i는 값이 1이여도 포인터변수는 주소 값이 int 형인 4씩증가한다.

포인터 연산:
-int *ptr++ (or ptr++) 주소값이 4씩증가 / double *ptr++ 주소값이 8씩증가

상수형태 문자열을 가리키는 포인터
- char str[]="hi 1234 !";       ==   char *str = "hi 1234 !";
-  char str1[]="12345";  //변수 형태의 문자열/ 데이터변경가능
   char *str2="12344";   //상수 형태의 문자열/ 데이터 변경불가능

포인터 배열:
 char *str[]={"hellow","hihi","byebye"}; 
 printf("%s %s %s\n",str[0],str[1],str[2]); 

 char arr1[]="good"; 
 char arr2[]="morning";
 char arr3[]="!!!"; 
 char *arr[]={arr1,arr2,arr3}; 
 printf("%s %s %s\n",arr[0],arr[1],arr[2]);



[6-3 포인터와 함수]

-함수의 인자로 배열 전달하기
배열 값을 통째로 함수의 매개변수에 전달 할 수 없다. 대신에 배열의 주소값을 전달한다.

void outarr(char **str, char *arr){  //*str[]   arr[]도가능(매개변수에서만 사용제한)
                                             //배열은 주소 값이므로 포인터형식으로 받는다.
printf("%s %s %s\n",str[0],str[1],str[2]);
printf("%c %c %c\n",arr[0],arr[1],arr[2]);
}
int _tmain(int argc, _TCHAR* argv[])
{
 char *str[]={"hellow","hihi","byebye"}; //문자열 배열
 char arr[]={'a','b','c'};                      //문자 배열
 outarr(str,arr);
return 0;
}



-포인터 대상의 const선언
포인터변수가 가리키는 저장된 값을 변경하는 것을 허용하지 않겠다는 것.
변경하면 안되는 값의 안정성을 높이기 위함

Ex)
int * const p1=&n1; //한번 가리킨 변수를 끝까지 가리킨다. 변수 값 바꿀 수 있다.
const int *p2=&n2;  //다른 변수를 가리킬 수 있다. 변수의 값은 바꿀 수 없다.

p1=&n2; //error
p2=&n1;

*p1=40;
*p2=40; //error


[6-4 다중 포인터]
dptr -> ptr -> num(3.14);
double num=3.14;
double *ptr = #
double **dptr = &ptr;      //세 변수 모두 값은 값을 출력한다.
                                  //그러나 각 변수의 주소 값은 다르다.


-다중 포인터의 필요성

Ex)좋은 않은 예
void swap(int  *dp1, int *dp2){
 int *temp = dp1;                
 dp1=dp2;                        
 dp2=*temp;
}
void main(){
 int n1=10, n2=20;
 int *p1, *p2;
 p1=&n1, p2=&n2;
 swap(p1,p2);
}                    //p1과 p2의 값이 swap되지 않는다.

좋은 예
void swap(int **dp1, int**dp2){   //*dp1, *dp2로 받는다 매개변수 또한 별도의 메모리이다.
 int *temp = *dp1;                
 *dp1=*dp2;                           //*dp1은 p1의 주소 값이다.
 *dp2=*temp;
}
void main(){
 int n1=10, n2=20;
 int *p1, *p2;
 p1=&n1, p2=&n2;
 swap(&p1,&p2);
}


-포인터 배열과 다중포인터
int arr1[]={1,2,3};
int arr2[]={3,4,5};
int arr3[]={5,6,7};

int *arr[]={arr1,arr2,arr3}; //포인터의 배열은 더블 포인터
int **parr= arr;             //더블포인터의 포인터는 더블포인터변수로 받아야 한다.



[6-5 다차원 배열과 포인터]

-배열기반 포인터 연산
int arr1[2][3];
int arr2[3][2];

arr1+1 // 4*3 = 12씩 주소 값 증가
arr2+2 // 4*2 = 8 씩 주소 값 증가    

즉 2차원 배월의 포인터 형은 1)type형과 2)배열의 가로의 길이를 전달해야 한다.
ex)
        int arr1[4][2]={1,2,3,4,5,6,7,8};
int (*ptr)[2];
ptr=arr1;
printf("%d\n",ptr[3][1]); //8출력

*주의 *str[4]  //포인터 배열
(*str)[4]//배열 포인터        헷갈리지 않게 해야 한다.


-2차원 배열을 함수 인자로 전달

void function(double (*str)[7])
      //매개변수일 때만 double str[][7] 는 위의 내용과 같다.




[6-6 함수 포인터]

변수 뿐만 아니라 함수 또한 메모리에 저장되므로 주소 값을 가진다.
  int                     function                (double num)
반환형     주소값을 가리키는 상수 값            매개 변수


함수 형 포인터는 1)반환형 정보   2)매개변수 정보     두가지가 선언되어야 한다.

Ex)
   int function(int i, double k){
   ~
   ~
   }
   void main(){
   int num1=10;
   double num2=3.14;
   void (*fact)(int double) = function; // 함수 포인터
   fact(num1,num2);                       // 함수 포인터로 함수 호출.
                                                    매개변수는 서로 타입형이 맞아야 한다.
  }


마지막으로 매개변수의 선언으로 함수 포인터 변수가 올 수 있음을 보여준다.

int whofirst(int age1, int age2, int (*fuc)(int n1, int n2)){ //세번째가 함수포인터 변수
return fuc(age1, age2);
}
int big(int n1, int n2){  //둘 중 큰 수를 반환하는 함수
if(n1>n2)
return n1;
else
return n2;
}
int small(int n1, int n2){ //둘 중 작은 수를 반환하는 함수
if(n1>n2)
return n2;
else
return n1;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int num1 = 10;
int num2= 5;
printf("%d\n",whofirst(num1,num2,big));    //10출력
printf("%d\n",whofirst(num1,num2,small));  //5출력
return 0;
}

댓글 없음:

댓글 쓰기