11.1 첨자 연산
11.1.1 배열의 내부적 처리
- C언어 배열의 특징
- C는 내부적으로 1차원 배열만 지원한다. 2차원 이상의 다차원 배열은 1차원 배열의 확장에 불과하다. C에는 2차원 배열이라는 것이 없다.
-
배열을 구성하는 배열 요소의 타입에는 전혀 제한이 없다. T형 변수를 선언할 수 있으면 T형 배열도 언제나 선언할 수 있다. 배열도 유도형 타입의 일종이며 따라서 배열 그 자체가 배열의 요소가 될 수 있다.
부분 배열 (SubArray) : 다른 배열에 포함된 배열
전체 배열 (모배열) : 부분 배열을 배열 요소로 가지는 배열
배열이 내부적으로 어떻게 처리되는가에 따라서 큰 차이점이 발생하는데 바로 1. 첨자 연산 방법과 2. 부분 배열의 자격 문제가 달라진다. 다차원 배열에서는 부분 배열만 단독으로 사용할 수 없지만 배열의 배열에서는 부분 배열 단독으로도 배열로 인정된다는 큰 차이점이 있다.
- 예제 SubArray
#include <stdio.h>
void arDump( void *array, int length ) ;
void main ( void ) { unsigned char ari[2][3] = { {1, 2, 3}, {4, 5, 6} } ;
arDump (ari, sizeof(ari)) ; arDump (ari[0], sizeof(ari[0])) ; arDump (ari[1], sizeof(ari[1])) ; }
void arDump( void *array, int length ) { int i; for ( i = 0 ; i < length ; i++ ) { printf("%02X ", *((unsigned char *)array+i)); } printf("\n"); } |
- 예제 SubArray2
#include <stdio.h>
void main ( void ) { char ar[] = "한국을 빛낸 사람들"; char ars[2][3][10] = { { "이순신", "강감찬", "김유신" }, { "유관순", "을지문덕", "신사임당" } } ;
printf("ar 배열 = %s\n", ar) ; printf("ar[1][1] = %s\n", ars[1][1]); } |
11.1.2 [ ]연산자
ptr이 임의의 배열을 가리키는 포인터이고 n이 정수 일 때
ptr[n] = *(ptr+n)
- 예제 ArrayIndex
#include <stdio.h>
void main ( void ) { int ar[5] = { 1,2,3,4,5 } ;
printf("ar[2] = %d\n", ar[2]) ; printf("ar[2] = %d\n", *(ar+2)) ; printf("ar[2] = %d\n", 2[ar]) ; } |
ptr[ n ] == ptr+2 == *(ptr+n)
ar[2][1] == *(*(ar+2)+1)
- ar+2
- *(ar+2)
- *(ar+2)+1
- *(*(ar+2)+1)
- 예제 ArrayIndex2
#include <stdio.h>
void main ( void ) { int ar[3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}} ;
printf("ar[2][1] = %d\n", ar[2][1]) ; printf("ar[2][1] = %d\n", *(*(ar+2)+1)) ;
printf("sizeof(ar+2) = %d\n", sizeof(ar+2)) ; printf("sizeof(*(ar+2)) = %d\n", sizeof(*(ar+2))) ; printf("sizeof(*(ar+2)+1) = %d\n", sizeof(*(ar+2)+1)) ; } |
- 배열명은 포인터 상수 이다.
- 포인터와 정수끼리 덧셈하면 sizeof(T)만큼 이동하고 그 결과는 포인터이다.
- *연산자는 포인터가 가리키는 번지의 내용을 읽는다.
11.2 포인터 배열
11.2.1 정의
포인터 배열(Array of Pointer)이란 요소가 포인터형인 배열이다.
int *arpi[5] ; // 포인터 변수 다섯 개
- 예제 PointerArray
#include <stdio.h>
void main ( void ) { char *arps[] = {"고양이", "개", "오랑우탄", "돼지", "지렁이"} ; int i ; for ( i = 0 ; i < 5 ; i++ ) { printf("%d\n", arps[i]) ; } } |
11.2.2 포인터 배열의 활용
- 예제 PASung
#include <stdio.h>
void main ( void ) { int *ar[3] ; int num[3] ; int i ;
for ( i = 0 ; i < 3 ; i++ ) { printf("%d반의 학생수를 입력하세요 : ", i+1) ; scanf("%d", &num[i]) ; ar[i] = (int *)malloc(sizeof(int)*num[i]) ; }
//< 여기서 성적을 처리한다.
for ( i = 0 ; i < 3 ; i++ ) { free(ar[i]) ; } } |
|
11.2.3 포인터와 배열
실행 도중 동적으로 메모리를 할당하면 *포인터형 변수로도 정수형 배열을 가리킬 수 있다.
pi = (int *)malloc(sizeof(int) * n) ;
이렇게 하면 pi도 정수형 배열처럼 행세할 수 있음
- 포인터는 변수인데 비해 배열은 상수이다.
- pi가 가리키는 배열의 크기는 동적으로 결정 할 수 있지만 ar이 가리키는 배열의 크기는 선언할 때 정적으로 결정된다.
- 배열은 그 자체가 크기 때문에 함수의 인수로 전달할 수 없지만 포인터는 대상체가 무엇이든간에 4바이트의 크기밖에 차지하지 않으므로 함수로 전달할 수 있다.
- 포인터는 대상체로 직접 이동해서 바로 읽으므로 액세스 속도가 빠르다.
int **papi ;
11.3 배열 포인터
11.3.1 배열 포인터
- 포인터 배열(Array of Pointer) : 그 원소가 포인터인 배열이다.
-
배열 포인터(Pointer to Array) : 배열의 번지를 담는 포인터 변수이다.
배열 포인터는 결국 포인터이다.
- 예제 ArrayPointer
#include <stdio.h>
void main ( void ) { char arps[5][9] = {"고양이", "개", "오랑우탄", "돼지", "지렁이"} ;
char (*ps)[9] ; int i ; ps = arps ;
for ( i = 0 ; i < 5 ; i++ ) { printf("%s\n", *ps++) ; } } |
11.3.2 배열 인수
- 예제 ArrayArg
#include <stdio.h>
int GetTotaForWeek(int (*pa)[7]) ;
void main ( void ) { int i; int ari[][7] = { {1,2,3,4,5,6,7}, {8,9,10,11,12,13,14}, {15,16,17,18,19,20,21} } ;
for ( i = 0 ; i < 3 ; i++ ) { printf("%d 주의 판매량 = %d\n", i+1, GetTotaForWeek(&ari[i])) ; } }
int GetTotaForWeek(int (*pa)[7]) { int i, sum = 0 ;
for ( i = 0 ; i < 7 ; i++ ) { sum += pa[0][i] ; } return sum ; } |
11.3.3 배열 인수 표기법
- 예제 ArrayPara1
#include <stdio.h>
void OutArray(int ar[5]) ;
void main ( void ) { int ar[] = {1,2,3,4,5} ;
OutArray(ar) ; }
void OutArray(int ar[5]) { int i ; for (i = 0 ; i < 5 ; i++ ) { printf("%d번째 = %d\n", i, ar[i]) ; } } |
void OutArray(int ar[]) == void OutArray(int *ar) == void OutArray(int ar[5]) |
- 예제 ArrayPara2
#include <stdio.h>
int GetArSum(int ar[], int size) ;
void main ( void ) { int ar[] = {1,2,3,4,5} ; int ar2[] = {6,7,8,9,10,11} ;
printf("총합 = %d\n", GetArSum(ar, sizeof(ar)/sizeof(ar[0]))); printf("총합 = %d\n", GetArSum(ar2, sizeof(ar2)/sizeof(ar2[0]))); }
int GetArSum(int ar[], int size) { int i, sum = 0 ;
for ( i = 0 ; i < size ; i++ ) { sum += ar[i] ; } return sum ; } |
11.3.4 이차 배열 인수
- 예제 TwoArrayPara
#include <stdio.h>
void func(int (*ar)[3], int size) { int i, j;
for ( i = 0 ; i < size ; i++ ) { for ( j = 0 ; j < 3 ; j++ ) { printf("ar[%d][%d] = %d\n", i, j, ar[i][j]); } } puts("") ; }
void main ( void ) { int ar1[2][3] = {{1,2,3}, {4,5,6}} ; int ar2[3][3] = {{7,8,9}, {10,11,12}, {13,14,15}} ;
func(ar1, 2) ; func(ar2, 3) ; } |
11.3.5 이차 배열 할당
char *p = (char *[4])malloc(sizeof(char)*3*4) ;
free(p) ;
- 예제 malloc2array
#include <stdio.h> #include <string.h>
void main ( void ) { int i ;
char (*p)[4] = (char (*)[4])malloc(sizeof(char)*3*4) ; strcpy(p[0], "dog") ; strcpy(p[1], "cow") ; strcpy(p[2], "cat") ; for ( i = 0 ; i < 3 ; i++ ) { puts(p[i]) ; } free(p) ; } |
- 예제 malloc2array2
#include <stdio.h> #include <string.h>
void main ( void ) { int n = 3, m = 4 ; int i ;
char **p ; p = (char **)malloc(sizeof(char *)*n) ;
for ( i = 0 ; i < n ; i++ ) { p[i] = (char *)malloc(sizeof(char)*m) ; }
strcpy(p[0], "dog") ; strcpy(p[1], "cow") ; strcpy(p[2], "cat") ;
for ( i = 0 ; i < n ; i++ ) { free(p[i]) ; } free(p) ; } |
|
11.3.5 &ar
- 예제 ampersandarray
#include <stdio.h>
void main ( void ) { int ar[5] = {1,2,3,4,5} ; int *p1 ; int (*p2)[5] ;
p1 = ar ; p2 = &ar;
printf("before = %p\n", p1) ; printf("before = %p\n", p2) ; p1++ ; p2++ ;
printf("before = %p\n", p1) ; printf("before = %p\n", p2) ; } |
11.4 배열과 문자열
11.4.1 문자열 상수
- 예제 StringConst
#include <stdio.h>
void main ( void ) { char name[] = "Yoo Dong Gon" ;
printf("This is a string Const\n") ; puts(name) ; } |
|
11.4.2 문자 배열 초기화
char str[] = "korea" ;
" " 으로 묶어서 선언 부분에 초기화
11.4.3 문자형 포인터
- 예제 CharArray
#include <stdio.h>
void main ( void ) { char str[] = "korea" ; char *ptr = "korea" ;
puts(str) ; puts(ptr) ;
ptr = "china" ; // str = "china" ;
str[0] = 'C' ; //ptr[0] = 'C' ; } |
11.4.4 문자열 배열
- 예제 StringArray
#include <stdio.h>
void main ( void ) { char arCon[][32] = {"korea", "america", "iran", "russia"} ; int i;
for ( i = 0 ; i <sizeof(arCon)/sizeof(arCon[0]) ; i++ ) { puts(arCon[i]) ; } } |
- 예제 StringArray2
#include <stdio.h>
void main ( void ) { char *pCon[] = {"korea", "america", "iran", "russia"} ; int i;
for ( i = 0 ; i < sizeof(pCon)/sizeof(pCon[0]) ; i++ ) { puts(pCon[i]) ; } } |
|
- 예제 String2Array
#include <stdio.h>
void main ( void ) { int x, y ; char arCon[][4][32] = { {"대한민국", "일본", "북조선 인민주의 공화국", "베트남"}, {"미국", "브라질", "칠레", "아르헨티나"}, {"영국", "헝가리", "체코슬로바키아", "루마니아"}, {"남아프리카 공화국", "우간다", "나이지리아", "케냐"}, {"오스트레일리아", "뉴질랜드", "유동곤", "공화국"} } ;
for ( y = 0 ; y < 5 ; y++ ) { for ( x = 0 ; x < 4 ; x++ ) { printf("%s", arCon[x][y]) ; if( x != 3 ) { printf(", ") ; } } puts("") ; } } |
중요 개념
- &, * 연산자의 기능과 포인터로 변수를 간접적으로 참조하는 방법
- 함수가 참조 호출로 실인수 값을 변경하는 방법과 원리
- 포인터가 타입을 가지는 이유와 포인터 연산의 동작
- 포인터를 이용한 동적 메모리 할당
'책정리 > 혼자 연구하는 C,C++ 1' 카테고리의 다른 글
13장 구조체 (0) | 2015.02.19 |
---|---|
12장 문자열 함수 (0) | 2015.02.19 |
10장 포인터 (0) | 2015.02.19 |
9장 배열 (0) | 2015.02.19 |
8장 표준 함수 (0) | 2015.02.19 |