2011. 2. 27. 02:09

int (*pArr)[4];
: int arr1[2][4], int arr2[3][4]와 같은 배열을 가리킬 수 있는 포인터
이렇듯 배열을 가리킬 수 있다고 해서 배열 포인터라 한다.

void show_data(int (*ptr)[4], int a);
    ==
void show_data(int ptr[][4], int a);  <= 함수의 매개변수 선언시에만 가능

#include <stdio.h>

void show_data(int (*ptr)[4], int a);
int main(void)
{
 int arr1[2][4]={1, 2, 3, 4, 5, 6, 7, 8};
 int arr2[3][4]={{1}, {2}, {3}};

 show_data(arr1, 2);
 show_data(arr2, 3);
 
 return 0;
}

void show_data(int (*ptr)[4], int a)
{
 int i, j;
 printf("-------Start Print----------\n");
 for(i=0; i<a; i++)
 {
  for(j=0; j<4; j++)
   printf("%d ", ptr[i][j]);
  printf("\n");

 }

}





☆int (*pArr)[4] 와 int* pArr[4]의 차이점☆
int (*pArr)[4]는 배열을 가리키는 포!인!터이다. (배열포인터)
  int형 변수를 요소로 지니고 포인터 연산시 4칸씩 이동하는 2차원 배열을 가리키는 포인터이다.


int* pArr[4]는 배!열!이다.(포인터배열).
  int형 변수의 주소 값 4개를 저장할 수 있는 배열이다.

Posted by Triany
2011. 2. 26. 20:23
1) 포인터가 가리키는 변수의 상수화

  int a = 10;
  const int*p = &a;
  *p = 30; //error!!
  a = 30; //ok
포인터 p가 가리키는 변수를 상수화 하겠다는 뜻. 즉 포인터 p가 가리키는 변수의 값을 못 바꾸게 하겠다는 뜻이다.
포인터 p를 통해서 변수 a의 값을 변경하는 것만 막는 것.


2)포인터 상수화
  int a = 10;
  int b = 20;
  int* const p = &a;
  p = &b; //error
  *p = 30; //ok
포인터 자체가 상수화 된것. 즉 포인터 p가 지니는 주소값을 변경할 수 없다는 뜻이다.


3)포인터 상수화 + 포인터가 가리키는 데이터도 상수화
  int a = 10;
  int b = 20;
   const int* const p = &a;
  p = &b; //error
  *p = 30; //error
Posted by Triany
2011. 2. 26. 20:17

 #include <stdio.h>
int main(void){
    int val;
    scanf("%d", &val);
    return 0;
}
scanf 함수는 내부적으로 사용자로부터 정수를 입력받은 다음, 변수 val에 접근해서 대입해야 한다.
이렇게 scanf함수 내에서 main 함수에서 선언된 지역 변수에 접근하기 위해서는 해당 변수의 주소를 알아야 한다. 그래서 scanf함수를 호출하면서 값이 채워질 지역 변수 val의 주소 값을 인자로 전달하고 있는것이다. 결국 Call-By-Reference에 해당한다.



char형의 배열로 문자열을 입력받을 때는 왜 &연산자를 붙여주지 않는 것일까?
 #include <stdio.h>
int main(void){
    char str[100];
    printf("문자열 입력 :");

    scanf("%s", str);
    return 0;
}
위 코드에서 배열 이름 str은 배열의 주소를 나타낸다. 그러므로 &연산을 할 필요가 없는 것이다.

'Language > C언어' 카테고리의 다른 글

배열포인터  (0) 2011.02.27
포인터와 const키워드  (0) 2011.02.26
배열을 함수 인자로 전달받는 방법  (0) 2011.02.26
문자열 배열  (0) 2011.02.26
메모리 동적 할당 _ 1] malloc 함수 - free 함수 - calloc 함수  (0) 2010.09.28
Posted by Triany
2011. 2. 26. 19:54

int pArr[]과 int *pArr[]은 완전히 동일한 것. 
=> 둘다 int형 포인터 변수임
(int pArr[]을 사용하는 이유: 함수의 매개 변수를 선언하는 데 있어서 인자로 배열이 전달된다는 것을 좀 더 명확히 할 수 있도록 "int pArr[]"이라는 선언을 허용하는 것일 뿐 


1)int *parr 방식

#include <stdio.h>


int arradd(int* parr, int n);

int main(void){
 int arr[10]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
 int sumofarr;

 sumofarr=arradd(arr, sizeof(arr)/sizeof(int));
 printf("배열의 총합 : %d", sumofarr);
 
 return 0;
}


int arradd(int* parr, int n)
{
 int sum=0;
 int i;

 for(i=0; i<n; i++)
  sum += parr[i];

 return sum;
}





2)int pArr[]방식

#include <stdio.h>


int maxvalue(int pArr[], int n);
int main(void){
 int arr[10]={4,8,3,7,2};
 int max;

 max = maxvalue(arr, sizeof(arr)/sizeof(int));
 printf("최대값 :%d\n", max);


 return 0;
}

int maxvalue(int pArr[], int n){
 int max, i;
 max=pArr[0];
 
 for(i = 1; i<n; i++){
  if(max<pArr[i])
   max=pArr[i];
 }

 return max;
}



둘다 완전히 같은 표현이지만, int arr[]아 같은 선언은 매개 변수 선언시 예외적으로 허용되는 방법에 지나지 않으므로, 되도록이면 int *arr과 같은 선언을 사용하는 것이 좋다.
(단 어느 방법으로 구현하든지 이해할 수 있도록 두 방법다 숙지해야 함.)
Posted by Triany
2011. 2. 26. 19:33

문자열 배열 : 여러개의 문자열을 저장할 수 있다.

char * arr[3]={"HTML, Java, JSP"};
printf("%s %s %s\n", arr[0], arr[1], arr[2]);
HTML JAVA JSP

Posted by Triany
2010. 9. 28. 00:02

'동적 할당(Dynamic Allocation)' : 힙에 메모리를 할당하는 것
'정적 할당(Static Allocation)' : 스택과 데이터 영역에 메모리를 할당


○ malloc 함수
malloc 함수는 동적으로 메모리를 할당하는 함수다. 곧 힙 영역에 메모리를 할당하는 함수라는 뜻이다.
다음은 함수의 원형이다.
#include <stdlib.h>

void* malloc(size_t size)

// 성공 시 할당된 메모리의 첫 번째 주소 리턴, 실패 시 ULL 포인터 리턴

할당하고자 하는 메모리의 크기를 함수 호출 시 바이트 단위로 전달하면, 그 크기만큼 메모리를 힙에 할당하게 된다.
그리고 할당한 메모리의 주소(첫 번째 바이트의 주소)를리턴한다. 만약에메모리 부족으로 인해서 메모리 할당에 실패했다면,
NULL포인터가 리턴되므로, 리턴된 포인터가 NULL인지 아닌지를 확인해야 할 것이다.

<참고>"메모리의 첫 번째 주소를 리턴한다고? 그렇다면 힙에 할당한 배열이나 변수에 접근하려면 포인터를 사용하는수 밖에 없겠네!" 그렇다! 힙에 할당된 메모리 공간에 접근하려면 포인터를 사용해야 한다. 따라서 포인터가 익숙치 않거나 다소 기억이 흐릿하다면 이쯤에서 포인터에 대한 내용을 복습하는것도 좋을 것이다.

이제 한가지만 더 살펴보면 되겠다. 리턴형이 void*(void 포인터)인 이유이다.

malloc은 단순히 메모리만 할당하는 함수이다. 예를 들어서 4를 인자로 전달하면서 malloc 함수를 호출하는 경우 4바이트 메모리를 힙에 할당할 것이다. 그리고 난 다음에 malloc 함수는 다음과 같은 고민에 빠진다.

"4바이트를 힙 영역에 할당하기를 바라는 군. 좋아! 0x1000번지에서부터 4바이트를 할당하자. 이제 주소 값 0x1000을 리턴해야 하는데 어떤 타입으로 리턴하지? int형 데이터를 저장하려나? 그러면 int*형으로 리턴해야 겠네, 아냐! 4바이트니까 float형 데이터를 저장할 수도 있어. 혹시 문자열을 저장하려는 건 아닐까?"

그리고 다음과 같은 결론을 내린다. "그냥 void*형으로 리턴해야 겠다. 알아서 용도에 맞게 형 변환해서 쓰라고 하지 뭐"


다시 본론으로 돌아와서, malloc함수 호출시 전달하는 인자 정보만을 가지고는 리턴해야 할 주소 값의 포인터 타입을 결정짓지 못한다. 따라서 void* 타입으로 주소값을 리턴하는 것이다.

이제 리턴 타입이 void*인 이유를 알 수 있을 것이다. 그렇다면 여러분은 리턴된 포인터를 가지고 무슨 작업을 해야 하는가? 용도에 맞게 포인터를 형 변환해야 한다. 예를 들어 int형 데이터를 저장하기 위해서 메모리를 할당했다면, 리턴되는 void*를 int*로 변환해야 할 것이다.

 int * i = (int*) malloc( sizeof(int) );


                   ↓

 int *i = (int*) malloc(4);




● free 함수

힙(Heap) 영역에 메모리를할당하는 것과 더불어 할당된 메모리를 해제하는 것도 프로그래머가 신경써야 할 내용이다.
(컴퓨터가 알아서 해 주지 않는다.)

만약에 프로그램상에서 메모리를 동적으로(malloc함수를 이용해서)할당만 한다면 어떻게 될까?
적절한 시기에 할당해 놓은 메모리를 해제해 주지 않는다면, 결국에 가서는 메모리가 부족하게 될 것이다. 당장은 메모리 부족 현상이 발생하지 않는다 하더라도, 불필요한 메모리를 해제하지 않고 그냥 내버려 두는 것은 성능상의 이유로도 바람직하지 않다. 따라서 할당된 메모리가 더 이상 필요하지 않은 경우에는 반드시 해제시켜 줘야 한다. 다음은 동적으로 할당된 메모리를 해제시켜 주는 함수의 원형이다.

#include <stdlib.h>

void free(void* ptr)

해제하고자 하는 메모리 공간을 가리키는 포인터를 인자로 전달하면, 해당 포인터가 가리키는 메몸리 공간은 해제된다. 매게 변수의 타입으로 void*로 선언되어 있다. 따라서 어떠한 포인터도 인자로 전달될 수 있다.

다음 에제를 통해서 지금까지 언급해 온 malloc 함수와 free 함수의 사용 예를 확인해 보자.
malloc과 free함수의 문법적 이해를 돕기 위한 것이다.
#include <stdio.h>
#include <stdlib.h>

int main (void)
{
    int* a;
    a = (int*) malloc(sizeof(int));    //메모리 할당
    if(a == NULL)                          //메모리 할당의 성공 유무 확인
    {
        puts("메모리 할당에 실패!");
        exit(1);
    }

    *a = 20;
    printf("힙에 저장된 변수 a : %d \n", *a);

    free(a); //메모리 해제
    return 0;
}



배열을 스택이 아닌 힙에 할당하게 된다면, array[j] 형식으로 선언 가능하다.
다음 예제를 살펴보자.
#include <stdio.h>
#include <stdlib.h>

void function(int);
int main (void)
{
    int m =0;
    fputs("배열의 크기를 입력하세요: ", stdout);
    scanf( "%d", &m);
    function(m);

    return 0;
}



void function(int i)
{
    //int array[i];  //배열을 선언하는 영역이 스택이었을 때문제점
    int* array = (int*)malloc(sizeof (int) *i); //동적 메모리 할당
    int j;
    if(array == NULL)
    {
        puts("메모리 할당에 실패!");
        exit(1); //비 정상적 종료를 의미함
    }
 
    /* 동적 할당한 메모리 사용 */
    for( j = 0; j < i ; j++)
        array[j] = j+1;
    for( j = 0; j < i; j++)
        printf( " %d ", array[j] );
    printf("\n");

    free(array); //할당된 메모리 소멸
}


 int* array = (int*)malloc(sizeof (int) *i); //동적 메모리 할당
/*
 다음을 보면 malloc 함수의 전달 인자가 조금 복잡하게 되어 있다. malloc  함수는 전달되는 매개 변수의 크기만큼 바이트 단위를 할당해 주기 때문이다. 즉 5를 전달하면 5바이트를 할당해 주고, 10을 전달하면 10바이트를 할당해 준다. 그렇다면 크기가 5인 int형 배열을 할당하려면 어떻게 표현해야 하는가? int가 4바이트이므로 5X4 = 20, 따라서 malloc(20)하면 된다. 그러나 이러한 표현보다는 malloc(size0f(int)*5)가 훨씬 부드럽고 사용하기에도 편리하다. int가 2바이트 인지 4 바이트 인지 신경 쓸 필요가 없기 때문이다.
길이가 123인 double형 배열을 선언해 보라! double이 8바이트 였던가? 그렇다면 123X8은? 음 머리가 아프다. 그러나 다음 표현은 double이 8바이트 였는지 조차 몰라도 사용 가능하다. malloc(szeof(double) * 123). 
*/

2차 배열에서 malloc 사용
function(int i)
{
int j
int** array = (int**)malloc(sizeof (int) *i);

for(j = 0; j < i ; j++)
{
    array[j] = (int*) malloc(sizeof(int) * i);
}

free(array);

//(int*) int형 포인터 캐스터 연산자, 형변환
//malloc은 주소를 반환하는 함수
//초기화는 for문 memset();

출처 : http://blog.naver.com/37441/80108113848






◐ calloc 함수
calloc 함수는 malloc 함수와 같은 기능을 가지고 있다. 즉 메모리를 동적으로 힙(heap)영역에 할당할 때 사용한다. 다만 사용하는 형태가 조금 다를 뿐이다.

#include <stdlib.h>

void *calloc(size_t elt_count, size_t elt_size)

//성공 시 할당받은 메모리의 포인터(void* 형), 실패 시 NULL 리턴

위 함수는 호출시 "elt_size 크기의 변수를elt_count개 만큼 저장할 수 있는 메모리 공간을 힙 영역에 할ㄹ당하라"라는 의미를 지닌다. 따라서 malloc(elt_count * elt_size) 함수 호출과동일한 효과를 나타낸다.

  int* arr = (int*)calloc(size, sizeof(int));                            ==  int* arr = (int*)malloc(size*sizeof(int));


다음에 소개되는 예제는 사용자가 요구하는 만큼의 메모리 공간을 동적으로 할당하고 그 크기만큼 숫자를 입력받는 예제이다.
#include < stdio.h >
#include < stdlib.h >

int main()
{
    int size, i;
    int * arr;
 
    printf( "Enter the number, to memory alloc : ");
    scanf("%d", &size);

    arr = (int*) calloc(size, sizeof(int) );
    //arr = (int*)malloc(size*sizeof(int));
    for(i = 0; i < size; i++)
        scanf("%d", &arr[i]);
   
    for(i = 0; i<size; i++)
       print("%d번째 요소 : %d \n", i, arr[i]);

    free(arr);
    return 0;
}



출처 : C프로그래밍 _ 윤성우저


'Language > C언어' 카테고리의 다른 글

배열을 함수 인자로 전달받는 방법  (0) 2011.02.26
문자열 배열  (0) 2011.02.26
C 언어의 메모리 구조  (0) 2010.09.27
[Random 함수] 난수 발생.  (0) 2010.09.26
[포인터] 함수 포인터 배열  (0) 2010.09.03
Posted by Triany
2010. 9. 27. 21:03



[스택(Stack), 힙(Heap) 그리고 데이터(Data)영역 ]
프로그램을 실행시키기 위해서는 메모리 공가ㅏㄴ이 필요하다. 지역 변수나 전역 변수를 선언하기 위해서도 메모리 공간이 필요하지 않은가? 그래서 컴퓨터는 여러분이 실행시킨 프로그램의 실행을 위해서 메모리 공간을 할당해 준다. 이렇게 해서 할당되는 메모리 공간은 크게 스택, 힙 그리고 데이터 영역으로 나뉘어 진다.
->쉬운 이해를 위해서 컴퓨터가 메모리 공간을 할당해 준다고 표현하였지만, 운영체제가 메모리 공간을 할당해 준다고 표현해야 정확한 표현이 된다.


할당 시기 : 프로그램이 실행될 때마다
할당 장소 : 메인 메모리에 할당되는데, 여기서 말하는 메인 메모리라 함은 RAM을 의미 함
할당 용도 : 프로그램 실행 시 필요한 메모리 공간(ex: 지역 변수, 전역 변수 선언을 위해)의 할당을 위해서

 전역변수
 Static 변수
  데이터 영역
 프로그래머 할당  힙(Heap)영역 
 지역변수
 매게변수
 스택(Stack)영역 

 * 데이터 영역(Data Area)
데이터 영역은 전역 변수와 static 변수가 할당되는 영역이다. 이 영역에 할당되는 ㅂ변수들은 일반적으로 프로그램의 시작과 동시에 할당되고, 프로그램이 종료되어야만 메모리에서 소멸된다. 즉, 데이터 영역에 할당된 변수는 프로그램이 종료될 때까지 존재한다는 특징을 지닌다. 전역변수와 static 변수는 프로그램이 종료될 때까지 존재하는 변수들이다. 이러한 특징이 데이터 영역의 특징과 일치한다.


* 스택 영역(Stack Area)
스택 영역은 함수 호출  시 생성되는 지역 변수와 매게 변수가 저장되는 영역이다. 이 영역에 할당된 변수는 함수 호출이 완료되면 사라진다는 특징을 지닌다. 이는 다른 메모리 영역과 확실히 비교되는 특징이다.

예를 들어 다음과 같은 stack이라는 함수가 있다고 가정해 보자

인자가 전달되면서 stack이라는 함수가 호출되면, 일단 매게 변수 a가 스택 영역에 올라가게 된다. 그리고 나서 지역 변수 b가 스택 영역에 올라갈 것이다. 반대로 stack 함수의 호출이 완료되고 나면, 변수 a와 변수 b는 스택영역에서 사라져 버린다.



* 힙 영역(Heap Area)
힙은 프로그래머가 관리하는 메모리 영역이다. 즉 프로그래머의 필요에 의해서 메모리 공간이 할당 및 소멸되는 영역이다.



◎배열은 반드시 상수로 선언해야 하는 이유
-배열 선언 시 배열의 길이는 반드시 상수로 표현해야 한다. 그 이유를 찾는 과정에서 힙 영역의 필요성-특징을 이해하게 될 것이다.
∴"스택과 데이터 영역에 할당될 메모리의 크기는 컴파일되는 동안(compile-time)에 결정되어야 하기 때문"
-힙은 데이터 영역이나 스택과 달리 런-타임에 필요한 만큼 메모리를 할당하고 해제할 수 있다.
"할당해야 할 메모리의 크기를 런-타임(프로그램이 실행되는 동안)에 결정해야 하는 경우, 유용하게 사용되는 메모리 공간이 바로 힙(Heap)영역이다."





출처 ;C프로그래밍 _ 윤성우
Posted by Triany
2010. 9. 26. 19:23

프로그램을 구현하다 보면 난수(Random Number)를 발생시켜야 하는 경우가 종종 있다. 여기서 말하는 난수란 임의의, 정해지지 않은, 무엇이 될지 모르는 수를 의미하는 것으로 무작위로 값을 생성해야 함을 의미한다.

ANSI표준에서는 이렇게난수를 생성할 때 사용할 수 있는 함수 rand를 제공하고 있다.

다음 예에서는 rand 함수의 사용 방법과 난수의 범위를 보여준다.
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
     int i;

     printf("난수의 범위 : 0부터 %d까지\n", RAND_MAX);

     for(i = 0; i < 5; i++)
          printf("난수 출력 : %d \n", rand() );

     return 0;
}



위의 예제를 여러 번 돌려보면 한가지 특징을 발견할 수 있다. 그것은 발생하는 난수가 규칙적이라는 것이다.
예를 들어서 처음 실행했을 때 생성된 난수가 21, 1, 43, 13, 2라면 다시 실행해 봐도 생성되는 난수는 21, 1, 43, 13, 2가 생성된다는 것이다. 이는 분명히 문제다! 왜냐하면 진짜로 난수가 생성되는 것이 아니기 때문이다. 따라서 rand 함수를 가리켜 의사 난수(pseudo-random number)를 생성하는 함수라고 하는 것이다. 의사 난수라는 뜻은 가짜 난수를 의미한다.

물론 여기에는 대안이 있다. srand함수를 사용하는 것이다.
#include <stdlib.h>

void srand( unsigned int seed );

함수 srand는 하나의 인자를 전달받는다. 이 인자를 가리켜 씨드(seed) 값이라 한다. 씨드란 씨앗이라는 뜻이다. 즉 난수 생성을 위해 씨앗을 심는 용도로 사용되는 함수이다. "콩 심은 데 콩 나고, 팥 심은 데 팥 난다."는 속담이 있듯이 씨드 값이 무엇이냐에 따라서 rand 함수 호출 시 생성되는 난수들은 달라지기 마련이다.

다음 예제는 씨드값을 입력 받아서 srand 함수를 호출하는 예제이다.
#include < stdio.h >
#include < stdlib.h >

int main(void)
{
     int seed, i;
 
    printf("씨드 값 입력: ");
    scanf("%d", &seed);
    srand(seed);    //씨앗을 심는다.
   
    for( i = 0; i < 5 ; i++)
        printf("정수 출력: %d \n", rand()); //열매를 수화ㅏㄱ한다.

    return 0;
}



srand 함수도 공부했으니 이제 진정한 난수를 발생시킬 수 있겠는가?
아니다!! 여전히 문제는 있다. 위 예제처럼 프로그램을 실행할 때마다 씨드 값을 입력받을 수는 없는 노릇 아닌가? 설사 입력받는다 해도 매번 다른 값을 입력받는다는 가정을 세우는 것도 무리가 있다. 한가지 방법은 있다. 시스템의 시간을 이용하는 것이다. 현재 여러분 컴퓨터의 시간 값을 얻어와서 srand 함수의 인자로 전달할 수만 있다면 문제는 해결이 된다. 왜냐하면 컴퓨터의 시간은 계속해서 변하기 때문이다.

그렇다면 컴퓨터의 현재 시간을 어떻게 얻어와야 할까? 헤더파일 time.h 에 선언되어 있는 time이라는 이름의 함수를 사용하면 된다. 이 함수는 컴퓨터의 현재 시간과 1970년 1월 일 이후의 시간적 차를 초 단위로 계산하여 반환해 준다(굉장하지 않은가?) 우리는 정확한 시간을 얻겠다는 것이 아니고, 프로그램 실행시 마다 변경되는 값을 얻겠다는 것이므로, 이 정도면 충분하다.


지금까지 이야기한 내용을 종합하여 진정한 난수를 발생시키는 예를 제시하겠다. 실행해 보면 매번 출력되는 난수의 값이 다르다는 것을 알 수 있을 것이다.
#include < stdio.h >
#include < stdlib.h >
#include < time.h >

int main(void)
{
    int i;
    srand( (int) time (NULL) ); //현재 시간을 이용해서 씨드 설정
    for( i = 0; i < 5; i++ )
        printf("정수 출력 : %d \n", rand() );

    return 0;
}


출처 :  C프로그래밍 _ 윤성우 저
Posted by Triany
2010. 9. 3. 14:13
함수 포인터 선언!
int (*fPtr1)(int);
: 함수포인터 fPtr1은 리턴형이 int이고 int형 인자 1개를 전달받는 모든 함수를 가리킬 수 있는 포인터가 된다.
void (*fPtr2)(int, int);
: 함수포인터 fPtr2는 리턴형이 void이고 int형 인자 2개를 전달 받는 모든 함수를 가리킬 수 있는 포인터가 된다.

 #include <stdio.h>

void Add(int a, int b);
void Sprint(char *str);
int main(void){
 char *string = "Function Pointer";
 int a=10, b=20;

 void (*fPtr1)(int, int) = Add;
 void (*fPtr2)(char*) = Sprint;

 fPtr1(a, b);
 fPtr2(string);

 return 0;
}

void Add(int a, int b)
{
 printf("덧셈 결과 : %d\n", a+b);
}
void Sprint(char *str)
{
 printf("입력된 문자열: %s\n", str);

}






포인터 배열과 같이 '함수 포인터를 원소로 갖는 함수 포인터 배열'을 생각할 수 있다.
다음은 배열의 크기가 4인 함수 포인터 배열을 선언하는 문장으로 배열의 각 원소가 가리키는 함수는 반환값이 void이고 인자목록이 (double*, double, double)이어야 한다.

    void (*pfary[4]) (double*, double, double)

위에서 선언된  배열에 함수 4개의 주소값을 저장하는 문장은 다음과 같다.
   
    pfary[0] = add;
    pfary[1] = subtract;
    pfary[2] = multply;
    pfary[3] = devide;

또는 간단하게 배열의 선언화 초기화 문장으로 처리할 수 있다.
   
    void (*pfary[4]) (double*, double, double) = {add, subtract, multiply, devide};

위의 것들을 사용하여 간단한 사칙연산 예제 프로그램을 작성해 보자.

 예제 10-17   출처 : C로 배우는 프로글밍 기초 p.327

 /*
   파일 : pfunarray.c
   목적 : 함수 포인터 배열을 이해하기 위한 예제
*/
#include <stdio.h>

void add(double*, double, double);
void subtract(double*, double, double);
void multiply(double*, double, double);
void devide(double*, double, double);

int main(void)
{
 double m, n, result;
 int opmenu;
 char *opstr[4] = {"더하기", "빼기", "곱하기", "나누기"};
 char op[4] = {'+', '-', '*', '/'};

 void (*pfary[4])(double*, double, double) = {add, subtract, multiply, devide};

 printf("사칙연산을 위하여 각 연산에 대한 번호를 입력하세요. >> \n");
 printf("[더하기] : 0, [빼기] : 1, [곱하기] : 2, [나누기] : 3 >> ");
 scanf("%d", &opmenu);
 if( !(0 <= opmenu && opmenu <= 3) )
 {
  printf("메뉴 입력이 잘못되어 프로그램을 종료합니다.\n");
  return 0;
 }

 printf("\n사칙연산을 수행할 실수 2개를 입력하세요. >> ");
 scanf("%lf %lf", &m, &n);

 //사칙연산을 배열의 첨자를 이용하여 수행
 pfary[opmenu](&result, m, n);
 printf("\n문장  : pfary[%d] 함수 호출\n", opmenu);
 printf("%s 수행 : %lf %c %lf == %lf\n\n", opstr[opmenu], m, op[opmenu], n, result);

 return 0;
}

void add(double *z, double x, double y)
{
 *z = x + y;
}
void subtract(double *z, double x, double y)
{
 *z = x - y;
}
void multiply(double *z, double x, double y)
{
 *z = x*y;
}
void devide(double *z, double x, double y)
{
 *z = x/y;
}



[+@  if문을 while문으로 고쳐서, 사용자가 임의로 종류하기 전까지 반복하는 식으로 변경해 보자.]
[      잘못된 수를 썼을 경우, 다시 입력하라는 문구가 뜨게 하자.]
Posted by Triany
2010. 9. 3. 13:33

값에 의한 전달(call by value)
주소에 의한 전달 (call by address)


 예제 10-15   (출처 : C로 배우는 프로그래밍 기초 p.321)

/*
 파일 : callbyaddrress.c
 목적 : 주소에 의한 호출과 값에 의한 호출을 비교하는 예제
*/
#include <stdio.h>

void incrementbyvalue(int number);
void incrementbyaddress(int *number);
int main(void)
{
 int number = 10;

 printf("함수 main()에서 \n");
 printf("\t지역변수 주소(number) = %p, number = %d\n\n", &number, number);

 incrementbyvalue(number);
 printf("\tincrementbyvalue(int number)를 호출 이후 =>> \n");
 printf("\t지역변수 주소(number) = %p, number = %d\n\n", &number, number);

 incrementbyaddress(&number);
 printf("\tincrementbyvalue(int *number)를 호출 이후 =>> \n");
 printf("\t지역변수 주소(number) = %p, number = %d\n\n", &number, number);

 return 0;
}

void incrementbyvalue(int number)
{
 number++;
}

void incrementbyaddress(int *number)
{
 (*number)++;
}




Posted by Triany