c by dissection

26
9장 Arrays and Pointers 장장장장장장장 장 9 장 Arrays and Pointers C By Dissection

Upload: kurt

Post on 15-Jan-2016

57 views

Category:

Documents


0 download

DESCRIPTION

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 차원 배열. 배열 이란 ? 데이터 형을 갖는 데이터 아이템들의 순서열 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: C By Dissection

9 장 Arrays and Pointers

전자정보공학부

제 9 장

Arrays and Pointers

C By Dissection

Page 2: C By Dissection

2

9 장 Arrays and Pointers

전자정보공학부

강 의 내 용

9.1 1 차원 배열

9.2 예제 : 각 문자 수 세기

9.3 배열과 포인터와의 관계

9.4 포인터 연산과 요소의 크기

9.5 함수로 배열 전달하기

9.6 정렬 알고리즘 : 버블 정렬

9.7 2 차원 배열

9.8 다차원 배열

9.9 동적 메모리 할당

Page 3: C By Dissection

3

9 장 Arrays and Pointers

전자정보공학부

9.1 1 차원 배열

배열 이란 ?– 데이터 형을 갖는 데이터 아이템들의 순서열

– 메모리에 순차적으로 저장되어 첨자 (index) 로 각 아이템들을 지정 – 메모리 할당은 기저 주소 (base address) 에서부터 이루어지며 ,

배열의 이름은 이 기저 주소를 가리키는 포인터 상수

– 배열의 각 원소들은 인덱스 (index) 라고도 부르는 첨자를 사용 • index 는 반드시 정수형 상수 , 정수형 변수 , 정수형 수식

– int grade[3];• grade[0], grade[1], grade[2] : 세 개의 저장 공간 확보됨• grade[3] = 3; /* ERROR 배열의 범위 벗어남 */

Page 4: C By Dissection

4

9 장 Arrays and Pointers

전자정보공학부

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

Page 5: C By Dissection

5

9 장 Arrays and Pointers

전자정보공학부

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]=11a[3]=16, a[4]=23

sum = 0 + 7 + 8 + 11 + 16 + 23 = 65

Page 6: C By Dissection

6

9 장 Arrays and Pointers

전자정보공학부

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 & 범위 매우 중요 */

– 범위 초과하면 실행 시간 오류 발생 , 컴파일 체크 (Ⅹ)

Page 7: C By Dissection

7

9 장 Arrays and Pointers

전자정보공학부

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;

}

Page 8: C By Dissection

8

9 장 Arrays and Pointers

전자정보공학부

9.3 배열과 포인터와의 관계

배열이름 자체는 주소 또는 포인터 값 포인터와 배열의 메모리 접근 방식은 거의 동일 포인터는 주소를 값으로 갖는 변수 배열 이름은 상수 포인터로 취급되는 고정 주소

* 표– 변수 선언시 사용 : 포인터 변수 선언– 산술 연산자 사용 (c = a * b;) : 곱하기 연산자– 포인터 변수 앞에 사용 (*p = 100;)

• 포인터 p 가 가리키는 주소 ( 메모리 공간 ) 에 저장된 값 (data) 을

읽어오기 , 저장하기 , 수식 등에 사용됨

• *p = 100; /* 포인터 p 가 가리키는 메모리 공간에 100 을 저장하라는 의미 */

int a[100], *p;

Page 9: C By Dissection

9

9 장 Arrays and Pointers

전자정보공학부

9.3 배열과 포인터와의 관계

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] 와 같음 /* 매우 중요 */

int a[100], *p;

Page 10: C By Dissection

10

9 장 Arrays and Pointers

전자정보공학부

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 번지가 됨

Page 11: C By Dissection

11

9 장 Arrays and Pointers

전자정보공학부

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 는 같은 표현임단 , 함수의 인자로 전달될 때만

배열을 전달 받아서합계를 계산하여 반환하는 함수

Page 12: C By Dissection

12

9 장 Arrays and Pointers

전자정보공학부

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]);

}

Page 13: C By Dissection

13

9 장 Arrays and Pointers

전자정보공학부

9.6 정렬 알고리즘 : 버블 정렬

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

for (j = n - 1; i < j; --j) if (a[j-1] > a[j]) swap(&a[j-1], &a[j]);

Page 14: C By Dissection

14

9 장 Arrays and Pointers

전자정보공학부

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]

data_type variable_name[ number][ number ]; Array dimensions

Declarations of arrays

Remarks

int a[100]; a one-demensional array

int b[2][7]; a two-demensional array

int c[5][3][2]; a three-demensional array

Page 15: C By Dissection

15

9 장 Arrays and Pointers

전자정보공학부

9.7 2- 차원 배열 이차원배열의 elements

이차원 배열의 기억장소를 앞 테이블 같이 그려보았지만 실제로 컴퓨터 메모리에 저장되는 기억장소는 다음과 같다 . 일련의 메모리 공간에 차례대로 배열이 지정되는 것이다 .

row0 row1 row2

[Ex]

int a[3][5];

col1 col2 col3 col4 col5

row 1 a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]

row 2 a[1][0] a[1][1] a[1][2] a[1][3] a[1][4]

row 3 a[2][0] a[2][1] a[2][2] a[2][3] a[2][4]

a[0][0] a[0][1]

… a[0][4]

a[1][0]

. a[1][4]

a[2][0] … a[2][4]

&a[0][0] &a[0][1]

&a[0] &a[1] &a[1]

&a[1][4] &a[1][0]

Page 16: C By Dissection

16

9 장 Arrays and Pointers

전자정보공학부

9.7 2- 차원 배열

2 차원 배열 element 를 access 하는 여러 가지 방법

– a[ i ] 는 a 의 i 번째 행– a[ i ][ j ] 는 배열의 i 번째 행과 j 번째 열의 원소– 배열 이름 a 는 &a[0] 와 같다 .

– a[i][j] 형식으로 사용하는 것이 편리함

Expressions equivalent to a[ i ][ j ]

*( a[ i ] + j )

( *( a + i ) ) [ j ]

*( ( *( a + j ) ) + j )

*( &a[0][0] + 5 * i + j )

Page 17: C By Dissection

17

9 장 Arrays and Pointers

전자정보공학부

9.7 2- 차원 배열int a[2][3], *p ;

p = &a[0][0]; /* p = a[0]; 와 같음 */

/* a[0] : a[0][0] 를 가리키는 address */

p + 1 &a[0][1] a[0] + 1

p + 2 &a[0][2] a[0] + 2

p + 3 &a[1][0] a[0] + 3 a[1] + 0

p + 4 &a[1][1] a[0] + 4 a[1] + 1

p + 5 &a[1][2] a[0] + 5 a[1] + 2

a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]

a[0] a[1]

p

같은 표현 이지만 컴파일 시 : Warning 발생 'int *' differs in levels of indirection from 'int (*)[3]'

p = a;

p = &a[0];

p = &a[0][0] ;

p = a[0];

Page 18: C By Dissection

18

9 장 Arrays and Pointers

전자정보공학부

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 sum_one_dem (int *a); int sum(int a[][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 (? 같음 ?) */

Page 19: C By Dissection

19

9 장 Arrays and Pointers

전자정보공학부

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 */}

Page 20: C By Dissection

20

9 장 Arrays and Pointers

전자정보공학부

9.8 다차원 배열 다차원 배열의 초기화

[Ex]

int a[ 2 ][ 2 ][ 3 ] = { { {1,1,0}, {2,0,0} }, { {3,0,0}, {4,4,0} } };

[Ex]

int a[ 2 ][ 2 ][ 3 ] = { 0 };

모든 원소들은 0 으로 초기화 된다 .

[Ex]

int a[ ][ 2 ][ 3 ] = { { {1, 1}, {2} }, { {3}, {4, 4} } };

Page 21: C By Dissection

21

9 장 Arrays and Pointers

전자정보공학부

9.9 동적 메모리 할당

C- 언어에서는 동적 메모리 할당을 위해 calloc(), malloc(), free() 함수 제공 함 <stdlib.h> 포함 시켜야 함 어디에서 메모리를 할당 받나 ?

– 누구한테 : System OS 으로부터– 어디에서 : 메인 메모리의 Heap 부분에서– heap? 일반적인 변수 , 함수를 위한 메모리와 다른 영역임– 할당 받은 것이기 때문에… 반드시 반환해야 함 (free)– 왜 동적 할당을 쓰나 ?

• 시스템의 메인 메모리는 한정된 자원임

• 한정된 메모리 공간을 효율적으로 사용하기 위함

Page 22: C By Dissection

22

9 장 Arrays and Pointers

전자정보공학부

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); /* 반드시 해야 함 */

Page 23: C By Dissection

23

9 장 Arrays and Pointers

전자정보공학부

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) */

Page 24: C By Dissection

24

9 장 Arrays and Pointers

전자정보공학부

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); 하기 전에 작성하는 것이 좋음 */

Page 25: C By Dissection

25

9 장 Arrays and Pointers

전자정보공학부

기 타

배열에서 매우 주의해야 할 것– 배열변수의 첨자 (index) 값이 그 범위를 초과하는 것

동적 메모리 할당을 사용할 경우– calloc(), malloc() 함수 사용 시 : 성공 여부 확인 필요

– 반드시 할당 받은 메모리를 반환 (free) 해야 함

포인터와 배열 그리고 함수 인자 전달에 관해서– 포인터 , 배열 , 함수 인자 전달방식을 이해하면 C- 언어가 보임

– 함수 인자 전달 방식• 함수의 헤더 부분 선언 하는 요령 ex: int sum(int *a, int n);• 함수의 선언 부분을 보고 함수를 Call 하는 요령• 함수의 Call 은 다른 함수 안에서 임 ex: sum(&arry[0], 5);

Page 26: C By Dissection

9 장 Arrays and Pointers

전자정보공학부

수고하셨습니다 .

Array and Pointers

포인터를 알면 C- 언어가 보입니다 .