Chapter 14 포인터
주소 Address 주소 값 이용 장단점 메모리에는 그 메모리의 저장장소의 위치를 나타내는 주소 값이라는 것이 있다. 메모리는 연속적인 저장공간의 집합으로 유일한 주소를 갖는다. 주소(address)는 1바이트마다 1씩 증가하도록 메모리에는 연속적인 번호가 구성 프로그래머는 주소 값을 십진수를 이용할 수는 있으나, 시스템은 주소 값의 표현을 기본적으로 16진수를 사용 주소 값은 저장 장소인 변수이름과 함께 기억 장소를 참조하는 또 다른 방법 주소 값 이용 장단점 주소 값을 이용하면 보다 편리하고 융통성 있는 프로그램이 가능 그러나 복잡하고 어려운 단점
주소 연산자 주소 연산자 & 변수의 주소 값을 출력하는 방법 변수의 주소 값을 알아내려면 주소 연산자 &(ampersand)를 이용 즉 주소 연산자를 변수 앞에 기술하는 전위 연산자로서 &i와 같이 기술하면 그 변수 i의 주소 값이 반환 함수 scanf()에서 일반 변수 인자 앞에는 주소 연산자 &를 사용 변수의 주소 값을 출력하는 방법 변수 age 앞에 &를 기술하면 age의 주소 값이 반환되고, 이를 출력하려면 변환명세 %p를 이용 주소 값을 16진수로 출력하려면 변환명세로 %p를, 10진수로 출력하려면 변환명세로 %u를 이용 int age; scanf(“%d”, &age); int age; printf(“%p, %u”, &age, &age);
예제 소스 address.c 자료형 char형 변수와 int형 변수, double형 변수를 각각 선언하여 값을 저장한 후, 저장 값과 주소 값을 각각 출력하는 프로그램 포인터 변수의 저장값이나 주소값을 출력하기 위해서는 변환 명세에 %p나 %u로 출력 일반 변수 앞에 주소 연산자 &를 이용하면 주소 값을 얻음
포인터 변수 포인터 변수는 일반 변수와는 다르게 변수에 저장되는 값이 메모리의 주소(address) 값만을 저장할 수 있는 특별한 변수 포인터 변수 없이 프로그래밍이 가능하나, 포인터 변수를 이용하면 프로그램이 간결하고 효율적이므로 포인터 변수를 이용 이러한 포인터 변수는 일반 변수와 구별되며, 변수 선언 방법도 일반 변수 선언과 다르게 사용
포인터 변수 선언 다음은 정수 int 자료형 변수의 주소 값을 저장할 수 있는 포인터 변수 ptr을 선언하는 구문 즉 선언 시에 별표(*)는 그 변수가 포인터 변수임을 나타낸다. 자료형 int는 포인터가 가리키는 변수의 자료형 위 선언은 다음과 같이 별표 *의 위치가 변수 자료형 int와 변수명 사이 어디에 위치하든 관계없이 가능 즉 다음도 가능, 위 표기가 가장 일반적인 방법 int는 포인터 변수 ptr에 저장되는 주소의 변수가 갖는 자료형을 나타낸다. 변수 ptr은 자료형 int의 포인터라고 말하며, *ptr 자체가 자료형 int의 변수라고 생각할 수 있다. int *ptr; int * ptr; int* ptr;
포인터 자료형 여러 개의 포인터 변수를 한 번에 선언 여러 자료형의 포인터 다음은 잘못 의미는 ptr1은 int 형 포인터를 의미하나 ptr2와 ptr3은 단순히 int형을 표현 그러므로 세 변수를 모두 포인터 변수로 선언하려면 다음과 같이 여러 자료형의 포인터 포인터 변수는 그 포인터가 가리키는 변수의 자료형에 맞추어 형을 선언해야 함 변수 i의 자료형이 int이기 때문에 int 형 변수의 주소를 저장하기 위해서는 int 형 포인터를 이용해야 함 아래 주석 문장에 표현하듯이 double 형 주소를 저장하기 위해서는 double *ptr 변수를 이용해야 함 int* ptr1, ptr2, ptr3; int *ptr1, *ptr2, *ptr3; int i; //double phi = 3.14; int *ptr = &i; //double *ptr = φ
포인터 변수의 값 포인터 변수는 주소(address) 값만을 저장 위 구문은 변수 ptr에는 변수 i의 주소 값이 저장 변수 ptr은 초기 값이 변수 i의 주소가 지정되었으므로 *ptr은 변수 i 자체를 의미 int i = 3; int *ptr = &i;
포인터 변수 메모리 의미 int i = 3; int *ptr = &i;
역참조 연산자 역참조 연산자 * 구문 *ptr = i + 2;을 이용 int i = 3; int *ptr = &i; 역참조 연산자는 포인터 변수 앞에 연산자 *를 붙이면 그 포인터가 가리키는 변수를 지칭 구문 *ptr = i + 2;을 이용 변수 i의 값이 2 증가 연산자 *는 포인터 변수를 뒤에 기술하면 역참조(dereference) 연산자 *ptr은 ptr이 가리키는 변수 자체를 의미한다. 여기서는 ptr이 변수 i의 주소 값을 가지므로 *ptr은 변수 i를 의미한다. int i = 3; int *ptr = &i; *ptr = i + 2;
예제 소스 pointer.c 다음은 int형 변수 i와 이 변수의 포인터인 변수 pi를 선언하여, 변수 pi를 이용하여 변수 i의 내부 값을 변환하는 프로그램 변수 i와 pi의 주소 값과 내부 저장 값을 각각 출력하는 기능도 수행
NULL 포인터 포인터 변수에 저장하는 NULL 포인터 변수를 선언할 때 다음과 같은 문장을 자주 이용한다. 포인터 변수가 다른 변수를 가리키는 저장 값을 갖는지를 검사하는데 이용 int *ptr = NULL #define NULL ((void *)0) if ( ptr == NULL ) { … }
배열과 포인터 포인터를 이용하여 배열의 각 원소를 참조하는 방법 그렇다면 point는 무엇으로 이용할 수 있을까? 다음과 같은 배열 선언에서 변수 point[]는 int 형 원소 6개를 저장할 수 있는 배열을 의미 그렇다면 point는 무엇으로 이용할 수 있을까? 위에서 point는 배열의 첫 원소인 point[0]의 주소 값을 나타낸다. 즉 다음이 성립한다. point는 주소 상수로 배열의 첫 번째 원소의 주소 값을 나타낸다. 주소 상수 point에 역참조 연산자 *를 이용하면 바로 변수 point[0]를 지칭하므로 다음이 성립 int point[] = {95, 88, 76, 54, 85, 82}; point == &point[0] *point == point[0]
배열 이름을 이용한 원소 참조 그렇다면 point + 1은 무엇일까? 주소 상수에 더하기 1의 의미인 point + 1은 주소값 point의 다음 원소의 주소값을 의미 즉 point + 1은 &point[1]을 의미하며, point[1]의 주소값 그러므로 point를 이용하여 배열 원소의 주소 참조 가능 주소 값 point + 1은 실제의 주소 값으로 살펴보면 point의 실제 주소 값에 int 형의 크기만큼 더한 주소 값을 의미 배열 이름인 point와 역참조 연산자 *를 적절히 이용하면 다음과 같은 식이 성립 *point == point[0] *(point + 1) == point[1] *(point + 2) == point[2]
배열을 포인터로 표현 위 식을 일반화 하면 배열의 범위 내에서는 다음 식이 성립한다. 포인터 변수인 point의 덧셈은 단순히 i 바이트 만큼을 증가시키는 것이 아니라 point가 가리키는 변수인 int형 크기를 i 번째 만큼 증가한 주소 값을 결과로 갖는다. *(point + i) == point[i] 연산식 *(point + 1)는 *point + 1 과는 다른 결과이므로 반드시 괄호를 이용해야 한다.
예제 소스 Arraypointer.c 배열 point[]의 원소 값과 주소 값을 출력하는 프로그램을 작성 배열 point[]에는 성적 10개를 초기화하고, 배열 원소를 참조하는 point[i]를 이용하여 먼저 원소 값을 출력 다음에는 point+i의 주소 값을 출력하고, 이에 대응하는 원소 값을 역참조 연산자 *를 이용하여 *(point+i)를 출력 정수형 변수 aryLength를 다음과 같은 식으로 저장하면 배열을 순차적으로 접근하는 반복문에서 제한 값으로 적절히 이용 가능 식 sizeof (point)는 배열 point가 할당한 저장공간의 크기를 바이트로 반환하므로 다음 식의 변수 aryLength에는 배열 원소의 수가 저장 연산식 point+1과 point+2의 실제 주소값의 차이는 배열의 원소 자료형이 int이기 때문에 sizeof (int)의 값인 4인 것을 알 수 있음 aryLength = sizeof (point) / sizeof (int);
소스와 결과
배열 합 함수 배열의 합을 구하는 함수를 구현 함수의 인자로 배열을 이용하는 방법 한 가지는 배열 선언을 그대로 이용하는 방법 단지 배열의 크기 10을 인자에 int ary[10]로 기술해도 되지만 10은 별 의미가 없기 때문에 int ary[]로 기술 함수 sumary()로 배열 ary[]의 모든 원소의 합을 구하는 함수 함수 sumary()에서는 인자를 두 개 사용 인자 SIZE는 앞의 인자인 배열의 원소의 개수를 전달 함수를 배열 point가 선언된 메인 함수 내부에서 호출하려면 다음과 같이 기술 int point[] = {95, 88, 76, 54, 85, 82}; int sumary(int ary[], int SIZE) { int sum = 0, i = 0; for (i = 0; i < SIZE; i++) { sum += ary[i]; } return sum; sum = sumary(point, 6);
포인터 인자 이용 함수 sumary의 함수 헤더 부분을 기술하는 다른 방법 Call by value 다음과 같이 첫 번째 인자를 int형 포인터로 선언하는 방법 함수 구현에서는 sum += ary[i]를 주소 값의 역참조 연산자 *를 이용한 sum += *(ary + i)를 이용해도 같은 기능을 수행 결론적으로 함수의 형식 인자에서 int ary[]나 int *ary나 같은 의미 Call by value 함수의 인자로 배열이나 포인터를 이용하는 경우, 배열 이름이나 배열 원소의 첫 번째 원소의 주소 값을 인자로 넘기면 됨 함수 형식 인자에 포인터나 배열을 사용하는 방법을 주소에 의한 호출(call by address) int sumary(int *ary, int SIZE) { int sum = 0, i = 0; for (i = 0; i < SIZE; i++) { // sum += ary[i]; sum += *(ary + i); } return sum; sum = sumary(point, 6); //sum = sumary(&point[0], 6);
배열 인자 함수 배열을 인자로 하는 다양한 함수 처리 프로그램 반복문 for 문 블록에서 배열 원소의 합을 구하는 문장 함수의 인자로 1차원 배열과 배열의 크기를 이용하여 인자로 주어진 배열의 모든 원소의 합을 구하여 반환하는 함수를 여러 방법으로 작성 네 개의 함수의 원형은 어느 것을 이용하더라도 모두 동일한 의미 반복문 for 문 블록에서 배열 원소의 합을 구하는 문장 세 개(sum += ary[i]; sum += *(ary + i); //sum += *ary++;) 중에서 어느 것을 이용하여도 배열의 합 계산 가능 int sumary(int ary[], int SIZE); int sumaryp(int *ary, int SIZE); int sump(int *ary, int SIZE); int sump2(int *ary, int SIZE); int sumary(int ary[], int SIZE) { int sum = 0, i = 0; for (i = 0; i < SIZE; i++) { sum += ary[i]; // sum += *(ary + i); // sum += *ary++; } return sum;
예제 소스 Aryfunction.c 일차원 배열의 합을 구하는 다양한 함수 처리 프로그램
예제 소스 Aryfunction.c
위에서 구한 함수 sump2 반복문 for 내부에서 sum += *(ary + i)는 sum += *ary++로 대체 가능 연산식 *ary++은 연산자 우선 순위에 따라 *(ary++)을 의미 후위 증가 연산자 (ary++)는 우선 순위가 가장 높기 때문 int sump2(int *ary, int SIZE) { int sum = 0, i = 0; for (i = 0; i < SIZE; i++) { // sum += ary[i]; // sum += *(ary + i); sum += * ary++; // sum += *(ary++)을 의미 } return sum;
배열상수++ 메인 함수에서 배열 point의 주소 상수 point를 이용하여 위와 같은 코딩 방식이 가능할까? 위 소스의 sum += point[i]를 sum += *point++로 구현하는 것이 가능할까? 결론은 불가능하다. 이유는 point는 변수가 아닌 상수이므로 증가연산자의 피연산자로 이용이 불가능하기 때문 int main(void) { int i = 0, sum=0, aryLength; int point[] = {95, 88, 76, 54, 85, 33, 65, 78, 99, 82}; aryLength = sizeof (point) / sizeof (int); for (i = 0; i < aryLength; i++) { // sum += point[i]; sum += *(point++); } printf("메인에서 구한 합은 %d\n", sum);
포인터변수++ point를 하나의 다른 포인터 변수에 저장하고 이용하면 가능 int main(void) { int i = 0, sum=0, aryLength; int point[] = {95, 88, 76, 54, 85, 33, 65, 78, 99, 82}; int *pi = point; aryLength = sizeof (point) / sizeof (int); for (i = 0; i < aryLength; i++) { //sum += point[i]; sum += *(pi++); } printf("메인에서 구한 합은 %d\n", sum);
예제 소스 ptrincrement.c 다음 소스와 같이 배열의 모든 원소의 값을 더하는 방법을 네 가지 방식의 프로그램으로 작성 다른 포인터 변수 pi를 이용하는 방법도 가능
다중 포인터 포인터의 포인터 포인터 변수의 주소 값을 갖는 변수를 포인터의 포인터 이러한 포인터의 포인터를 다중 포인터라고도 하는데, 다음과 같이 변수 선언에서 *를 여러 번 이용하여 다중 포인터 변수를 선언 다중 포인터 변수를 이용하여 일반 변수를 참조하려면 역참조 연산자를 여러 번 이용 즉 위의 변수 dpi를 이용하여 변수 i의 값을 20으로 수정하려면 int i = 10; int *pi = &i; int **dpi = π **dpi = 20;
이중 포인터 이용 이중 포인터 이용 프로그램 변수 int 형 i에 10을 저장한 후, 포인터 변수 pi에는 i의 주소를, 다시 포인터 변수 dpi에는 pi의 주소를 저장 이 세 변수를 이용하여 다음과 같이 실행해 보자. 위 소스의 실행 결과는 변수 i의 값이 증가 즉 변수 i, 연산식 *pi, **dpi는 모두 같은 변수 i를 나타냄 int i = 10; int *pi = &i; int **dpi = π *pi = i + 2; //i = i + 2; **dpi = *pi + 2; //i = i + 2; i == *pi == **dpi
예제 소스 Doubleptr.c 이중 포인터를 이용 프로그램
포인터 배열 의미 선언 초기 값 NULL 저장 포인터 배열이란 주소 값을 저장하는 포인터를 요소로 하는 배열 포인터 배열은 다음과 같이 선언 위 포인터 배열에는 다른 int 형 변수의 주소 값을 저장 초기 값 NULL 저장 포인터 배열을 위와 같이 선언하면 포인터 배열의 크기만큼 배열이 메모리에 할당되고 각 원소의 내부 값은 모두 NULL로 채워진다 pAry[0] NULL pAry[1] pAry[2] int *pAry[3]; int *pAry[3] = {NULL};
포인터 배열 이용 포인터 배열 pAry의 각 원소에 아래와 같이 int 형 변수의 주소 값을 각각 대입 다음 그림은 위 소스가 실행된 후의 메모리 모습 int a = 50, b = 30, c = 40; pAry[0] = &a; pAry[1] = &c; pAry[2] = &b;
예제 소스 Ptrary.c 포인터 배열 이용 프로그램
이차원 배열 이름 이차원 배열에서 배열 이름 tAry는 무엇일까? 그러면 tAry[0]는 무엇인가? 포인터 상수 tAry[0]는 배열의 첫 번째 원소 tAry[0][0]의 주소 값 &tAry[0][0]을 갖는 포인터 상수 결론적으로 배열이름 tAry는 포인터 상수 tAry[0]의 주소 값을 갖는 포인터 상수, 그러므로 다음이 성립 다음은 포인터 상수 tAry[0]와 tAry의 모습을 표현 점선인 그림은 상수를 표현, 상수는 저장 장소는 아님 만일 배열의 첫 번째 원소인 tAry[0][0]의 주소 값이 [12FF68]이라면 상수 tAry와 tAry[0]는 모두 [12FF68] 값을 갖는 상수 int tAry[][3] = {{1, 20, 12}, {3, 5, 16}}; &tAry[0][0] == tAry[0] tAry[0] == *tAry
이차원 배열 여러 의미 일차원 배열에서 연산자 sizeof (배열명)를 이용하면 배열의 크기 연산 sizeof에서 알 수 있듯이 배열명 tAry는 이차원 배열을 대표하며, tAry[i]는 (i+1)행을 대표한다. 포인터 상수인 tAry[0]와 tAry의 역참조 연산자를 이용하면 다음과 같은 식을 만족한다. 포인터 상수인 tAry[0]가 &tAry[0][0]이라면 tAry[1]은 &tAry[1][0]이다. 그러므로 역참조 연산자를 이용하면 다음과 같은 식을 만족한다. sizeof (tAry) == 24 (이차원 배열의 크기 = 6*4 ) sizeof (tAry[0]) == 12 (1행의 크기 = 4*3 ) sizeof (tAry[0][0]) == 4 (원소의 형인 int의 크기) tAry[0][0] == *tAry[0] == 1 tAry[0] == *tAry == 12FF68 tAry[0][0] == *tAry[0] == 1 tAry[1][0] == *tAry[1] == 3
배열 포인터 상수 포인터 상수인 tAry[0]의 연산식 tAry[0] + 1은 무엇을 의미할까? 즉 연산식 tAry[0] + 1은 포인터 상수 tAry[0]에 다음 정수에 해당하는 주소 값을 의미하므로 &tAry[0][1]이다. 마찬가지로 연산식 tAry[0] + 2는 &tAry[0][2]을 의미한다. 포인터 상수인 tAry의 연산식 tAry + 1은 무엇을 의미할까? 연산식 tAry + 1은 포인터 tAry가 가르키는 배열 상수의 다음 배열 상수의 주소값 즉 연산식 tAry + 1은 &tAry[1]을 의미한다. 연산식 tAry + i은 배열 tAry의 i+1번째 행의 첫 번째 원소의 주소 값이 있는 상수를 가리키는 포인터이다. &tAry[0][1] == (tAry[0] + 1) == 12FF6C &tAry[0][2] == (tAry[1] + 2) == 12FF70 tAry[0][1] == *(tAry[0] + 1) == 20 tAry[0][2] == *(tAry[1] + 2) == 12 &tAry[0][0] == tAry[0] == *(tAry) == 12FF68 &tAry[1][0] == tAry[1] == *(tAry + 1) == 12FF74 tAry[0][0] == *tAry[0] == **(tAry) == 1 tAry[1][0] == *tAry[1] == **(tAry + 1) == 3
이차원 배열 포인터 상수 배열 이름을 이용한 원소 참조 이차원 배열 이름은 이중 포인터 지금까지 알아 본 포인터 상수 tAry와 tAry+1, tAry[0], tAry[1]을 배열과 함께 정리하면 다음과 같다. 이차원 배열 이름은 이중 포인터 다중 포인터 변수를 이용하여 일반 변수를 참조하려면 역참조 연산자를 여러 번 이용한다. 즉 배열 이름인 tAry는 이중 포인터이며, 이 tAry를 이용하여 변수 tAry[0][0]의 값을 20으로 수정하려면 다음 문장을 이용할 수 있다. **tAry = 20;
이차원 배열 주소 값 표현 int tAry[][3] = {{1, 20, 12}, {3, 5, 16}}; 이차원 배열에서의 각 원소의 주소 값을 표현하는 여러 방법 위 배열 tAry에서 첫 번째 원소인 tAry[0][0]의 주소 값을 표현하는 방법은 &tAry[0][0], tAry[0], *tAry 방법 int tAry[][3] = {{1, 20, 12}, {3, 5, 16}}; 배열 원소 주소 값의 표현 저장 tAry[0][0] tAry[0][1] tAry[0][2] [12FF68] &tAry[0][0] tAry[0] *tAry 1 [12FF6C] &tAry[0][1] tAry[0] + 1 *tAry + 1 20 [12FF70] &tAry[0][2] tAry[0] + 2 *tAry + 2 12 tAry[1][0] tAry[1][1] tAry[1][2] [12FF74] &tAry[1][0] tAry[1] *tAry + 3 *(tAry+1) 3 [12FF78] &tAry[1][1] tAry[1] + 1 *tAry + 4 *(tAry+1)+1 5 [12FF7C] &tAry[1][2] tAry[1] + 2 *tAry + 5 *(tAry+1)+2 16
예제 소스 twoDaryptr.c 이러한 이차원 배열의 주소 표현 방법을 점검해 보는 프로그램
이차원 배열 각 원소 참조 int tAry[][3] = {{1, 20, 12}, {3, 5, 16}}; tAry[0][0] 배열 원소 주소 값의 표현 저장 값의 표현 tAry[0][0] tAry[0][1] tAry[0][2] [12FF68] &tAry[0][0] tAry[0] *tAry 1 *tAry[0] **tAry (*(tAry))[0] [12FF6C] &tAry[0][1] tAry[0] + 1 *tAry + 1 20 *(tAry[0] + 1) *(*tAry + 1) (*(tAry))[1] [12FF70] &tAry[0][2] tAry[0] + 2 *tAry + 2 12 *(tAry[0] + 2) *(*tAry + 2) (*(tAry))[2] tAry[1][0] tAry[1][1] tAry[1][2] [12FF74] &tAry[1][0] tAry[1] *tAry + 3 *(tAry+1) 3 *tAry[1] *(*tAry + 3) **(tAry+1) (*(tAry+1))[0] [12FF78] &tAry[1][1] tAry[1] + 1 *tAry + 4 *(tAry+1)+1 5 *(tAry[1] + 1) *(*tAry + 4) *(*(tAry+1)+1) (*(tAry+1))[1] [12FF7C] &tAry[1][2] tAry[1] + 2 *tAry + 5 *(tAry+1)+2 16 *(tAry[1] + 2) *(*tAry + 5) *(*(tAry+1)+2) (*(tAry+1))[2]
원소 tAry[i][j] 표현 이차원 배열에서 원소 tAry[i][j]의 저장 값을 표현하는 여러 방법
예제 소스 twoDaryvalue.c 이러한 이차원 배열의 저장 값을 여러 방법으로 참조하는 방법을 점검해 보는 프로그램
값에 의한 전달 Call by value 함수의 구현에서 인자를 사용하는 방법 중에서 포인터가 아닌 일반 변수를 사용하면 값에 의한 전달(call by value) 방식 위 함수 increment1()는 함수를 호출하는 부분에서 실인자로 사용하는 변수 값이 증가하지 않음 위 소스와 같이 인자를 포인터 변수 number로 이용하여 구현하면 어떨까? int increment1(int number) { number++; return number; } int increment1(int *number) { … }
주소에 의한 전달 call by address 위에서 살펴 본 인자의 값을 1 증가시키는 함수 increment1()를 다음과 같이 수정한 것이 주소에 의한 호출 방식으로 구현한 함수이다. 함수 구현 부분의 문장 (*number)++은 ++(*number)으로 하여도 같은 기능을 수행 그러나 이 문장을 *number++나 *(number++)로 사용해서는 같은 결과를 얻을 수 없으니 주의하기 바란다. void incrementbyreference(int *number) { (*number)++; }
주소에 의한 전달의 이해 함수 incrementbyreference() 내부에서 *num은 메인의 변수 number를 대신하는 연산식이므로 (*num)++을 수행하면 메인에 정의된 변수 number의 값이 1 증가하는 효과 함수 incrementbyreference()의 인자 부분을 int *num으로 하든 int *number로 하든 형식 인자에 기술된 변수명은 메인 함수의 int number와는 전혀 무관한 형식 인자 변수 이름 함수의 인자로 배열을 이용하는 경우, 모두 주소에 의한 호출 방식을 이용하므로 함수의 호출 시 배열의 첫 원소 주소 값만이 복사되고 실제 배열 값들은 복사되지 않는다.
예제 소스 Callbyaddress.c 주소에 의한 호출 방식으로 1 증가 처리 프로그램 메인 함수의 int 형 변수 number의 값에 10을 저장한 후, 값에 의한 호출 방식과 주소에 의한 호출 방식, 두 방식으로 함수를 각각 구현 변수 number를 실인자로 각각 두 개의 함수를 차례로 호출하여 변수 number에 저장된 결과 값을 비교 두 함수는 다음과 같이 구현 void incrementbyvalue(int number) { number++; } void incrementbyreference(int *number) (*number)++;
예제 소스
프로그램 연습 프로그램 목적 행렬의 곱을 수행하는 프로그램을 작성하자. 행렬의 곱은 아래와 같이 정의 위의 행렬 A와 B의 곱을 행렬 C라 하면 행렬 C를 구성하는 각 원소는 다음과 같다. 위에서 알 수 있듯이 행렬 A와 B의 곱을 수행하려면 행렬 A의 열의 수와 행렬 B의 행의 수가 같아야 한다.
프로그램 구현 행렬 곱 연산 위 이차원 배열 선언을 새로운 자료형 matrixA와 matrixB로 선언하는 방법을 알아보자. 다음과 같이 typedef를 이용하여 matrixA와 matrixB를 정의하면 matrixA와 matrixB를 각각 (2x3)과 (3X2)의 이차원 배열의 새로운 자료형 키워드로 이용 int a[2][3] = {{1, 2, 2}, {2, 3, 1}}; int b[3][2] = {{1, 2}, {1, 3}, {1, 2}}; #define ROWS 2 #define COLS 3 … typedef int matrixA[ROWS][COLS]; typedef int matrixB[COLS][ROWS]; matrixA a = {{1, 2, 2}, {2, 3, 1}}; matrixB b = {{1, 2}, {1, 3}, {1, 2}};
행렬 곱 모듈 행렬 곱 연산 행렬 A의 1행 (1, 2, 2)와 행렬 B의 1열 (1, 1, 1)을 각각 곱하여 더한 값이 곱 행렬 C의 C[i][j]의 값(i=1, j=1) C[i][j] = 1*1 + 2*1 + 2*1 void multiply(resultC r, matrixA a, matrixB b) { int i, j, k; for (i=0; i < ROWS; i++) { for (j=0; j < ROWS; j++) { for (k=0; k < COLS; k++) { //r[i][j] += a[i][k] * b[k][j]; *(r[i] + j) += *(a[i]+ k) * *(b[k] + j); }
소스와 결과