1 / 26

C By Dissection

C By Dissection. 제 9 장 Arrays and Pointers. 강 의 내 용. 9.1 1 차원 배열 9.2 예제 : 각 문자 수 세기 9.3 배열과 포인터와의 관계 9.4 포인터 연산과 요소의 크기 9.5 함수로 배열 전달하기 9.6 정렬 알고리즘 : 버블 정렬 9.7 2 차원 배열 9.8 다차원 배열 9.9 동적 메모리 할당. 9.1 1 차원 배열. 배열 이란 ? 데이터 형을 갖는 데이터 아이템들의 순서열

kurt
Télécharger la présentation

C By Dissection

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. C By Dissection 제 9 장 Arrays and Pointers

  2. 강 의 내 용 • 9.1 1 차원 배열 • 9.2 예제 : 각 문자 수 세기 • 9.3 배열과 포인터와의 관계 • 9.4 포인터 연산과 요소의 크기 • 9.5 함수로 배열 전달하기 • 9.6 정렬 알고리즘 : 버블 정렬 • 9.7 2 차원 배열 • 9.8 다차원 배열 • 9.9 동적 메모리 할당

  3. 9.1 1차원 배열 • 배열 이란? • 데이터 형을 갖는 데이터 아이템들의 순서열 • 메모리에 순차적으로 저장되어 첨자(index)로 각 아이템들을 지정 • 메모리 할당은 기저 주소(base address)에서부터 이루어지며, 배열의 이름은 이 기저 주소를 가리키는 포인터 상수 • 배열의 각 원소들은 인덱스(index)라고도 부르는 첨자를 사용 • index는 반드시정수형 상수, 정수형 변수, 정수형 수식 • int grade[3]; • grade[0], grade[1], grade[2] : 세 개의 저장 공간 확보됨 • grade[3] = 3; /* ERROR 배열의 범위 벗어남 */

  4. 9.1 1차원 배열 • 변수이름 자체a에는 a[0]의 주소1000이 저장됨 • a는 포인터(주소를 담을 수 있는 저장 공간) 상수(변하지 않음)임. • &a[0] : 1000 • &a[1] : 1004 • &a[2] : 1008 • &a[3] : 1012 • &a[4] : 1016 • a : 1000

  5. 9.1 1차원 배열 #include <stdio.h> /*Fill and Print an array. */ #define N 5 int main(void) { int a[N]; /* allocate space for a[0] to a[4] */ int i, sum = 0; for (i = 0; i < N; ++i) a[i] = 7 + i * i; for (i = 0; i < N; ++i) printf("a[%d] = %d ", i, a[i]); for (i = 0; i < N; ++i)sum += a[i]; printf("\nsum = %d\n", sum); /* print the sum */ return 0; } a[0]=7, a[1]=8, a[2]=11 a[3]=16, a[4]=23 sum = 0 + 7 + 8 + 11 + 16 + 23 = 65

  6. 9.1 1차원 배열 • 초기화 • 배열은 선언문 내에서초기화될 수 있음 • float x[7] = {-1.1, 0.2, 33.0, 4.4, 5.05, 0.0, 7.7}; • x[0] = -1.1, x[2] = 0.2, x[3] = 33.0, … , x[6] = 7.7 이 입력됨 • int n[4] = {2, 7}; • n[0] = 2, n[1] = 7, n[2] = 0, n[3] = 0이 입력됨 • int a[] = {3, 4, 5, 6};는 int a[4] = {3, 4, 5, 6};과 같음 • a[0] = 3, a[1] = 4, a[2] = 5, a[3] = 6 • 배열 a의 원소 접근 (index) • int i, a[size]; • a[expr] = 4; /* 0 <= expr <= size-1 & 범위 매우 중요 */ • 범위 초과하면 실행 시간 오류 발생, 컴파일 체크(Ⅹ)

  7. 9.2 예제 : 각 문자 수 세기 #include <stdio.h> /* Count each uppercase letter separately. */ #include <ctype.h> int main(void) { int c, i, letter[26]; for (i = 0; i < 26; ++i) letter[i] = 0; /*init array to zero 매우 중요*/ while ((c = getchar()) != EOF) /* count the letters */ if (isupper(c)) ++letter[c - 'A']; /* letter[0] = ‘a’ or ‘A’… */ for (i = 0; i < 26; ++i) { /* print the results */ if (i % 6 == 0) printf("\n"); printf("%4c:%3d\n\n", 'A' + i, letter[i]); } return 0; }

  8. 9.3 배열과 포인터와의 관계 • 배열이름 자체는 주소 또는 포인터 값 • 포인터와 배열의 메모리 접근 방식은 거의 동일 • 포인터는 주소를 값으로 갖는변수 • 배열 이름은 상수 포인터로 취급되는 고정 주소 • * 표 • 변수 선언시 사용 : 포인터 변수 선언 • 산술 연산자 사용(c = a * b;) : 곱하기 연산자 • 포인터 변수 앞에 사용(*p = 100;) • 포인터 p가 가리키는 주소(메모리 공간)에 저장된 값(data)을 읽어오기, 저장하기, 수식 등에 사용됨 • *p = 100; /* 포인터 p가 가리키는 메모리 공간에100을 저장하라는 의미 */ int a[100], *p;

  9. 9.3 배열과 포인터와의 관계 int a[100], *p; • a[0]=2, a[1]=4, a[2]=8, … , a[99]=10 : 300, 304, 308, … , 696 번지의 메모리에 할당되었을 경우 • p = a; • p = &a[0]; 와 같으며… p에는 300 번지가 할당 됨 • *p의 값은? (2임) • 포인터는 주소 값을 담을 수 있는 메모리 공간 임 • 포인터 연산은 변수 형의 메모리 크기(sizeof(int) = 4)와 같은 크기로 이루어짐 • p = p + 2; ??? p에는 308 번지(300 + 2*4)할당 됨 • *p 의 값은? (8임) • *p = p[0], *(p+2) = p[2], *(p+i) = p[i]와 같음 /* 매우 중요 */

  10. 9.4 포인터 연산과 요소의 크기 • 포인터 연산에서의 요소의 크기는 • 포인터가 선언될 때의 변수형의 크기가 된다 • double *pt; • sizeof(double) = 8 : 포인터 연산의 크기 • 따라서… pt = 1000 번지 였다면… • pt = pt + 1; pt = 1008번지가 됨 • int *p; • sizeof(int) = 4 : 포인터 연산의 크기 • 따라서… p = 1000 번지 였다면… • p = p + 1; p = 1004번지가 됨

  11. 9.5 함수로 배열 전달하기 • 함수의 정의에서 배열로 선언된 형식 인자가 실제 포인터 • 배열이 함수의 인자로 전달 될 때 • 배열의 기저 주소는 값-기반 호출(call-by-value)로 전달 • 포인터는 주소를 담고 있는 메모리 공간 이므로 • 주소를 함수의 인자로 전달하는 방식을 call-by-reference라고 한다 int sum(int a[], int n) { int i, s = 0; for (i=0; i<n; ++i) s+= a[i]; return s; } int a[]와 int *a는 같은 표현임 단, 함수의 인자로 전달될 때만 배열을 전달 받아서 합계를 계산하여 반환하는 함수

  12. 9.6 정렬 알고리즘 : 버블 정렬 • 배열의 앞뒤원소를 순차적으로 비교하면서 바꿔 치기 하는 방식 • 작은 값 혹은 큰 값을 계속 앞으로 보내는 방식 • 반복을한 번하고 나면 가장 작은 값 혹은 큰 값이맨 앞으로 이동 됨 • 반복을n 번 하면 크기 순으로 정렬 됨 • 단점 : 반복 및 비교 횟수 많음(n2에 비례, 효율적인 방식 n*log2n에 비례) void swap(int *, int *); void bubble(int a[], int n) /* n is the size of a[] */ { int i, j; for (i = 0; i < n - 1; ++i) / * 반복을 n 번 */ for (j = n - 1; i < j; --j) / * 반복을 한 번 */ if (a[j-1] > a[j]) swap(&a[j-1], &a[j]); }

  13. 9.6 정렬 알고리즘 : 버블 정렬 for (j = n - 1; i < j; --j) if (a[j-1] > a[j]) swap(&a[j-1], &a[j]); a[0]=7, a[1]=3, a[2]=66, a[3]=3, a[4]=-5, a[5]=22, a[6]=-77, a[7]=2 a[0]=-77, a[1]=7, a[2]=3, a[3]=66, a[4]=3, a[5]=-5, a[6]=22, a[7]=2 a[0]=-77, a[1]=-5, a[2]=7, a[3]=3, a[4]=66, a[5]=3, a[6]=2, a[7]=22 a[0]=-77, a[1]=-5, a[2]=2, a[3]=7, a[4]=3, a[5]=66, a[6]=3, a[7]=22 a[0]=-77, a[1]=-5, a[2]=2, a[3]=3, a[4]=7, a[5]=3, a[6]=66, a[7]=22 a[0]=-77, a[1]=-5, a[2]=2, a[3]=3, a[4]=3, a[5]=7, a[6]=22, a[7]=66 a[0]=-77, a[1]=-5, a[2]=2, a[3]=3, a[4]=3, a[5]=7, a[6]=22, a[7]=66 a[0]=-77, a[1]=-5, a[2]=2, a[3]=3, a[4]=3, a[5]=7, a[6]=22, a[7]=66

  14. 9.7 2-차원 배열 • 2차원 배열 Syntax • int b[2][7]의 기억공간 (2*7 = 14개의 메모리 공간) • b[0][0], b[0][1], b[0][2], … , b[0][6] • b[1][0], b[1][1], b[1][2], … , b[1][6]

  15. 9.7 2-차원 배열 • 이차원배열의 elements • 이차원 배열의 기억장소를 앞 테이블 같이 그려보았지만 실제로 컴퓨터 메모리에 저장되는 기억장소는 다음과 같다. 일련의 메모리 공간에 차례대로 배열이 지정되는 것이다. row0 row1 row2 &a[0][0] &a[0][1] &a[1][0] &a[1][4] &a[0] &a[1] &a[1]

  16. 9.7 2-차원 배열 • 2차원 배열 element를 access하는 여러 가지 방법 • a[ i ]는 a의 i번째 행 • a[ i ][ j ]는 배열의 i번째 행과j번째 열의 원소 • 배열 이름a는 &a[0]와 같다. • a[i][j]형식으로 사용하는 것이 편리함

  17. 9.7 2-차원 배열 p a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] a[0] a[1] p = &a[0][0] ; p = a[0]; p = a; p = &a[0]; 같은 표현 이지만컴파일 시 : Warning 발생 'int *' differs in levels of indirection from 'int (*)[3]'

  18. 9.7 2-차원 배열 int sum(int a[][5]) { int i,j, sum=0; for(i = 0; i < 3; ++i) for(j = 0; j < 5; ++j) sum += a[i][j]; return sum; } 이차원 배열을 함수의 인자로 전달하기 ** 매우 중요 ** ** 함수의 헤더부분 선언 시 다음은 모두 같은 표현 ** int a[][5], int(*a)[5], int a[3][5] : 모두 같은 표현 함수의 인자전달 매우 중요 반드시 크기 필요 int main (void) { int i, j, grade[3][5], sum_1=0, sum_2=0; for (i=0; i<3; ++i) for(j=0; j<5; ++j) grade[i][j] = i*10 + j; sum_1 = sum(grade); for (i=0; i<3; ++i) sum_2 = sum_2 + sum_one_dem(grade[i]); return 0; } /* sum_1 == sum_2 (? 같음?) */ int sum_one_dem (int *a); int sum(int a[][5]); 같은 일을 하는 두 개의 함수가 선언되어 있을 때

  19. 9.8 다차원 배열 int sum(int a[][9][2]) { int i,j,k sum=0; for(i = 0; i < 7; ++i) for(j = 0; j < 9; ++j) for(k = 0; k < 2; ++k) sum += a[i][j]; return sum; } 3차원 배열을 함수의 인자로 전달하기 ** 매우 중요 ** ** 함수의 헤더부분 선언 시 다음은 모두 같은 표현 ** int a[][9][2], int(*a)[9][2], int a[7][9][2] : 모두 같은 표현 함수의 인자전달 매우 중요 반드시 크기 필요 int main (void) { int grade[7][9][2], total=0; for (i=0; i<7; ++i) for(j=0; j<9; ++j) for(k=0; k<2; ++k) grade[I][j][k] = i+j+k; total = sum(grade); /* sum(int a[][9][2]) Call */ }

  20. 9.8 다차원 배열 • 다차원 배열의 초기화 모든 원소들은 0으로 초기화 된다.

  21. 9.9 동적 메모리 할당 • C-언어에서는 동적 메모리 할당을 위해 • calloc(), malloc(), free()함수 제공 함 • <stdlib.h>포함 시켜야 함 • 어디에서 메모리를 할당 받나? • 누구한테 : System OS으로부터 • 어디에서 : 메인 메모리의 Heap 부분에서 • heap? 일반적인 변수, 함수를 위한 메모리와 다른 영역임 • 할당 받은 것이기 때문에…반드시 반환해야 함(free) • 왜 동적 할당을 쓰나 ? • 시스템의 메인 메모리는 한정된 자원임 • 한정된 메모리 공간을 효율적으로 사용하기 위함

  22. 9.9 동적 메모리 할당 • 동적 할당 함수 • void *calloc(size_t n, size_t size); • size_t Type ? : 일반적으로 unsigned int • void *:할당 받은 메모리의 시작 주소 • size_t n: (size 크기를 같는)n 개의 메모리 블록 할당 • size_t size:할당 되는 메모리의 한 개의 블록 크기 • 따라서 전체의 할당 메모리 크기는 n*size바이트 임 • 동적 할당 함수는 포인터를 반환하므로 할당 받은 메모리는 포인터 변수를 이용해야 만이 사용 가능(저장, 읽기, 수식 사용 등등) int *a; a = (int *)calloc(10, sizeof(int)); /* a[0], a[1], … , a[9] */] a[0] = 10; … if(a[2] == 1) … ; … ; 사용이 끝나면 free(a); /* 반드시 해야 함 */

  23. 9.9 동적 메모리 할당 • 동적 할당 함수 • void *malloc(size_t n); • calloc() 함수와 같으나 n바이트의 메모리 블록을 할당 int *a, *p; a = (int *)malloc(10*sizeof(int)); • calloc() 함수 : 할당 메모리 블록 초기화 됨 • malloc() 함수 : 할당 메모리 블록 초기화 안됨 • 두 함수 모두 실패하면 NULL 포인터 값 반환 됨 • 반환 성공 여부 확인 방법 if (a != NULL) …성공 else …실패 • 반드시 free() 해 줘야 함. free (a); /* 반환 된 뒤에는 사용 불가ex: a[2] = 10; (ERROR) */

  24. 9.9 동적 메모리 할당 #include <stdio.h> #include <stdlib.h> int main(void) { int *a, i, n, sum = 0; printf("\n%s", "An array will be created dynamically.\n\n" "Input an array size n followed by n integers: "); scanf("%d", &n); a = (int *)calloc(n, sizeof(int)); /* get space for n ints */ for (i = 0; i < n; ++i) scanf("%d", &a[i]); for (i = 0; i < n; ++i) sum += a[i]; free(a); /* free the space */ /* output routine 생략됨 */ return 0; /* 참고 사항 : output routine은 */ } /* free(a); 하기 전에 작성하는 것이 좋음 */

  25. 기 타 • 배열에서 매우 주의해야 할 것 • 배열변수의 첨자(index)값이 그 범위를 초과하는 것 • 동적 메모리 할당을 사용할 경우 • calloc(), malloc() 함수 사용 시 : 성공 여부 확인필요 • 반드시 할당 받은 메모리를 반환(free) 해야 함 • 포인터와 배열 그리고 함수 인자 전달에 관해서 • 포인터, 배열, 함수 인자 전달방식을 이해하면 C-언어가 보임 • 함수 인자 전달 방식 • 함수의 헤더 부분 선언 하는 요령ex: int sum(int *a, int n); • 함수의 선언 부분을 보고 함수를 Call 하는 요령 • 함수의 Call은 다른 함수 안에서 임ex: sum(&arry[0], 5);

  26. 포인터를 알면 C-언어가 보입니다. 수고하셨습니다. Array and Pointers

More Related