A BOOK ON C CHAP 6

Download Report

Transcript A BOOK ON C CHAP 6

A Book on C
University of Inchon
배 열
• 배열은 첨자가 붙은 변수를 사용하여 여러
개의 동질적 값을 표현할 수 있는
데이터형이다.
• C언어에서 배열과 포인터는 밀접한 관련이
있다.
• 문자열은 문자의 1차원 배열이다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 1
A Book on C
University of Inchon
1차원 배열(1)
• 프로그램에는 종종 동질적 자료가 사용된다.
예를 들면
int grade0, grade1, grade2;
대신, 배열을 사용할수 있다.
int grade[3];
The number of elements.
It must be positive.
배월원소의 첨자는 항상 0부터 시작된다.
배열첨자는 0~ size - 1 까지의 범위를 갖는다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 2
A Book on C
University of Inchon
1차원 배열(2)
따라서 다음과 같은 관계가 성립한다.
int a[size];
/* space for a[0],..., a[size-1] */
lower bound = 0
upper bound = size - 1
size = upper bound + 1
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 3
A Book on C
University of Inchon
1차원 배열(3)
• 배열 크기를 다음 예에서 보는 것과 같이 기호상수로
정의하는 것이 좋은 프로그래밍 기법이다.
#define N
100
int a[N];
/* space for a[0],..., a[99] */
다음과 같이 for문에서 배열을 사용할 수 있다.
for(i = 0; i < N; ++i)
sum += a[i];
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 4
A Book on C
University of Inchon
배열의 초기화(1)
• 배열은 auto, extern, static기억 영역 클래스는 될
수 있지만, register는 될 수 없다.
one_dimensional_array_initializer ::= {initializer_list}
initializer_list ::= initializer {, initializer}0+
initializer ::= constant_integral_expression
예를 들면
float f[5] = {0.0, 1.0, 2.0, 3.0, 4.0};
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 5
A Book on C
University of Inchon
배열의 초기화(2)
• 초기자 리스트가 초기화되는 배열원소 개수보다
적다면, 남은 원소들은 0으로 초기화된다.
예를 들면
int a[100] = {0};
다음의 경우 a의 모든 원소들은 0으로 초기화 된다.
• 만일 외부와 정적 배열이 명시적으로 초기화 되지
않았다면, 시스템은 디폴트로 모든 원소를 0으로
초기화 한다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 6
A Book on C
University of Inchon
배열의 초기화(3)
• 배열의 크기를 기술하지 않고, 일련의 값으로
초기화되도록 선언하면, 초기값의 수가 암시적으로 배열의
크기가 된다.
그러므로
int a[] = {2, 3, 5, -7};
=
int a[4] = {2, 3, 5, -7};
이 사실은 문자배열도 마찬가지이다.
=
char s[] = "abc";
char s[] = {'a', 'b', 'c', '\0'};
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 7
A Book on C
University of Inchon
포인터(Pointer)
• 포인터는 프로그램에서 메모리를 액세스하고
주소를 다루기 위해 사용된다.
• v 가 변수이면, &v 는 저장된 값의 메모리
위치, 또는 주소이다.
포인터 선언
int *p;
변수 p가 int 에 대한 포인터 형임을 나타낸다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 8
A Book on C
University of Inchon
포인터 p에 값을 할당한 예
p
p
p
p
=
=
=
=
0;
NULL;
&i;
(int *)1776;
/* equivalent to p = 0; */
/* an absolute address in memory */
p가 포인터이면, *p는 p가 주소인 변수의 값을
나타난다.
어떤 의미에서 *는 &와 상반되는 연산자이다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 9
A Book on C
University of Inchon
포인터 메커니즘의 사용 예
다음과 같이 선언하자
int a = 1, b = 2, *p;
a, b, p 는 다음과 같이 메모리에 저장된다.
a
b
1
p
2
?
p = &a;
a
b
1
p
2
b = *p 는 b = a 와 동일하다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 10
A Book on C
University of Inchon
Sample Program(1)
/* Printing an address, or location. */
#include <stdio.h>
int main(void)
{
int i = 7, *p;
p = &i;
printf("%s%d\n%s%p\n",
"
Value of i:
"Location of i:
return 0;
" *p,
" p);
}
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 11
A Book on C
University of Inchon
Sample Program(2)
• 출력은 시스템마다 다를 것이며, 한 시스템의
결과는 다음과 같다.
Value of i : 7
Location of i : effffb24
• 메모리에서 변수의 실제 위치는 시스템 종속적이다.
• 즉 p는 주소 또는 위치를 가지며, 식 *p는 그 주소에
저장된 값을 p의 형 선언에 따라 적절히 변환된 값을
가진다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 12
A Book on C
University of Inchon
포인터 수식이 계산되는 방법
Declarations and initializations
int
i = 3, j = 5, *p = &I, *q = &j, *r;
double x;
Expression
p == & i
* * & p
r= & x
7* * p/* q+ 7
* (r = & j) *= * p
Equivalent expression
p = = (& i )
* (* (& p))
r = (& x)
(((7 * (* p))) / (* q)) + 7
(* (r = (& j))) *= (* p)
Value
1
3
/* illegal */
11
15
이 표에서 r에 &x값을 배정하려 하였다. r은 int형의
포인터이고, 식 &x는 double형의 포인터이므로,
잘못된 배정이다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 13
A Book on C
University of Inchon
Legal & Illegal Assignments
Declarations
int *p;
float q;
viod *v;
Legal assignments
Illegal assignments
p=
p=
p=
p=
p = 1;
v = 1;
p = q;
0;
(int *) 1;
v = q;
(int *) q;
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 14
A Book on C
University of Inchon
금지 사항 :
• 다음의 금지사항을 주의하라.
Constructs not to be pointed at
Do not point at constant.
&3
/* Illegal */
Do not point at ordinary expressions.
&(k + 99)
/* Illegal */
Do not point at register varialbles.
register v;
&v
/* Illegal */
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 15
A Book on C
University of Inchon
참조의 의한 호출(Call By Reference)
• 함수간 자료전달을 "call by reference”로
수행하기 위해서는 함수 정의부의 매개변수
리스트에 포인터가 사용되어야 한다.
• 예를 들면
void swap(int *p, int *q)
{
int tmp;
tmp = *p;
*p = *q;
*q = tmp;
}
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 16
A Book on C
University of Inchon
배열과 포인터 사이의 관계(1)
• 배열 이름은 그 자체로 주소 또는 포인터 값,
포인터이다. 배열과 포인터가 메모리에
접근하는 방법은 거의 동일하다.
• 하지만 미묘한 차이점이 있다.
•
포인터 변수는 다른 주소들을 가질 수 있다.
• 이와 대조적으로 배열 이름은 고정된 주소나
포인터 값을 가진다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 17
A Book on C
University of Inchon
배열과 포인터 사이의 관계(3)
• a가 배열이고, i는 int형이라고 가정하자.
a[i]
= *(a + i)
두 식은 같다.
• 식 a[i] 는(0부터 시작하여) 배열의 i번째
원소값이다. 반면 *(a + i)는 식 a + i를
간접참조하게 되는데, 이 식은 i번째
원소위치를 포인트하는 포인터식이다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 18
A Book on C
University of Inchon
배열과 포인터 사이의 관계(4)
•
p 가 포인터이면, 유사한 방식으로 다음 두 식은
같다.
p[i] = *(p + i)
• 이것은 포인터 변수에 배열 표기법을 사용할 수
있음을 의미한다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 19
A Book on C
University of Inchon
포인터 연산 및 원소 크기(1)
• 포인터 연산은 C언어의 강력한 특징 중 하나이다.
• 변수 p가 특정형에 대한 포인터이면, 식 p+1은
그 형의 다음 변수를 저장하거나 액세스할 수
있도록 올바른 기계 주소를 생성한다.
• 유사한 방식으로 p + i 나 ++p ,p += i 와
같은 포인터 식은 모두 유효하다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 20
A Book on C
University of Inchon
포인터 연산 및 원소 크기(2)
• 이 두 가지 식을 해석하는 데는 중요한 차이점이
있다.
• 다음 코드는 이 사실을 설명해 준다.
double a[2], *p, *q;
p = a;
/* points to base of array */
q = p + 1;
/* equivalent to q = &a[1]; */
printf("%d\n", q - p);
/* 1 is printed */
printf("%d\n", (int) q - (int) p); /* 8 is printed */
대부분 기계에서 double 형은 8바이트로 저장된다. p가
double형을 포인트하고 있고, q가 다음 double형을
포인트하고 있다면, 배열 원소 측면의 차이는 1이지만,
메모리 위치 측면에서의 차이는 8이다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 21
A Book on C
University of Inchon
함수 인자로서의 배열(1)
• 함수정의에서 배열로 선언된 형식 매개변수는
실질적으로는 포인터이다.
• 표기법상의 편리함을 주기 위하여 컴파일러는
배열 표기법 [ ]을 매개변수로서 포인터를
선언하는 데 사용할 수 있게 한다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 22
A Book on C
University of Inchon
함수 인자로서의 배열(2)
• 이 개념을 설명하기 위해, double형 배열 원소의
합을 계산하는 함수를 작성해 보자.
double sum(double a[], int n)
{
int
i;
double sum = 0.0;
/* n is the size a[] */
for(i = 0; i < n; ++i)
sum += a[i];
return sum;
}
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 23
A Book on C
University of Inchon
calloc() 과 malloc()을 이용한 동적 메모리 할당(1)
• C 는 표준 라이브러리로 함수 calloc() 와
malloc() 를 제공하며 이들 함수의 원형은
stlib.h에 정의되어 있다.
• calloc 이라는 함수명은 인접한
할당(contiguous allocation)을 나타내며,
malloc 은 메모리 할당(memory allocation)을
뜻한다.
• 프로그래머는 배열, 구조체, 공용체의 영역을
동적으로 생성하기 위해 calloc() 과 malloc()
을 사용한다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 24
A Book on C
University of Inchon
calloc() 과 malloc()을 이용한 동적 메모리 할당 2)
• 함수calloc() 은 2개의 인자를 가지는데 모두
size_t 형이다.
calloc(n, el_size)
각 원소의 크기가 el_size 바이트인 n개 원소로
이루어진 배열을 저장할 수 있는 메모리를
할당한다.
• 그 메모리 영역은 모든 비트가 0으로 초기화 된다.
• 호출이 성공하면 배열의 베이스 주소를
포인트하는 void * 형의 포인터를 리턴한다.
호출이 실패하면 NULL 을 리턴한다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 25
A Book on C
University of Inchon
calloc() 과 malloc()을 이용한 동적 메모리 할당 3)
• malloc() 도 유사한 방식으로 사용된다.
이 함수는 size_t 형의 하나으 인자를 취한다.
• 호출이 성공하면 메모리상의 요구된 영역을
포인트하는 void * 형의 포인터를 리턴한다.
실패하면 NULL 이 리턴된다.
• calloc() 과 달리 malloc() 함수는 설정한 메모리
영역을 초기화 하지 않는다. 큰 프로그램에서는
malloc() 의 실행 시간이 적게 걸린다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 26
A Book on C
University of Inchon
문 자 열(1)
• 문자열은 char 형의 1차원 배열로 볼 수 있다.
• 일반적으로 C 언어에서 문자열은 “end-of-string”
기호인 \0, 즉 널문자로 끝난다.
• 문자열은 가변적인 길이를 가지지만, 최대 길이가
문자열의 크기인 배열로 생각할 수 있다. 문자열의
크기는 \0 기호까지 포함한 기억 장소를 말하며,
무자열의 한계를 넘지 않는 범위 내에서 문자열을
조작하여야 한다.
• 문자열 상수는 큰따옴표 “ “안에 기술된다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 27
A Book on C
University of Inchon
문 자 열(2)
• 예를 들어, "abc”는 마지막 원소가 널문자 \0ㅇ니
크기 4의 문자 배열로 볼 수 있다.
• 문자열 상수는 문자 상수(charater constant)와는
다르다는 사실을 주목해야 한다.
• 예를 들어 ”a" 와 'a' 는 동일하지 않다. 배열 "a" 는
첫 번째 원소가 ‘a’ 값이고 두 번째 원소가 '\0’ 값인
두 원소를 갖게 된다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 28
A Book on C
University of Inchon
문 자 열(3)
• 컴파일러는 문자열 상수를 배열 이름처럼 포인터로
취급한다. 이 포인터 값은 문자열의 베이스 주소이다.
• 다음 코드를 고려해 보자.
char *p = "abc";
printf("%s %s\n", p,
p + 1);
/* abc bc is printed */
• 변수 p 에는 문자열 "abc”의 베이스 주소가 배정된다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 29
A Book on C
University of Inchon
표준 라이브러리에 있는 문자 조작함수 (1)
• char *strcat(char *s1, const char *s2);
이 함수는 2개의 문자열을 인자로 받아들여, 이 문자열을 결합하여
결과를 s1에 저장한다. 프로그래머는 s1이 결과를 저장할 충분한
영역을 갖도록 주의해야 한다. 문자열 s1이 리턴된다.
• int strcmp(const char *s1, const char *s2);
두 문자열이 인자로 전달된다. s1과 s2를 사전적 순서로 비교하여
그 결과를 다음과 같이 int형의 함수값으로 리턴한다.
s1 > s2이면, 양의 정수값
s1 = s2이면, 0
s1 < s2이면, 음의 정수값
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 30
A Book on C
University of Inchon
표준 라이브러리에 있는 문자 조작함수(2)
• char *strcpy(char *s1, const char *s2);
문자열 s2 가 \0 에 도달할 때 까지 s1으로 복사된다. s1에
어떤 값이 존재하든지 덮어 기록되며, s1은 결과를 저장할
충분한 크기의 영역을 갖고 있어야 한다. s1값이
함수값으로 리턴된다.
• int strlen(const char *s);
\0 를 포함하지 않고, 문자의 개수를 계산하여 리턴한다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 31
A Book on C
University of Inchon
표준 라이브러리에 있는 문자 조작함수(3)
문자 조작 함수들이 다음 표에서 설명되었다.
Declarations and initializations
char s1[] = “beautiful big sky country”,
s2[] = “how now brown cow”;
Expression
strlen(s1)
strlen(s2 + 8)
strcmp(s1, s2)
Statements
printf(“%s”, s1 + 10);
strcpy(s1 + 10, s2 + 8)
strcat(s1, “s!”);
printf(“%s”, s1);
멀티미디어와 가상환경 연구실(Marvelab)
Value
25
9
negative integer
What gets printed
big sky country
beautiful brown cows!
Chap. 6 - 32
A Book on C
University of Inchon
다차원 배열
• C 언어에서는 배열의 배열을 포함한 어떠한
형의 배열도 허용한다.
• 2차원 배열은 [ ][ ]쌍으로 표시하며, 이 개념은
더 높은 차원의 배열에도 적용된다.
Examples of declarations of arrays
int
int
int
a[100];
b[2][7];
c[5][3][2];
멀티미디어와 가상환경 연구실(Marvelab)
Remarks
a one-demensional array
a two-dimensional array
a three-dimensional array
Chap. 6 - 33
A Book on C
University of Inchon
main() 함수의 인자
• 일반적으로 argc 와 argv 라는 두 인자가
운영체제와 교신하기 위해 main() 에서
사용된다.
• 변수 argc 는 명령어 라인의 인자 개수를
포함하는 정수이다.
• 배열 argv 는 문자열의 배열로 생각할 수 있는
char형 포인터 배열이다.
• 원소argv[0] 는 명령어 자체의 이름을 포함하고
있고, argc 의 값은 항상 1이상의 값을 가진다.
멀티미디어와 가상환경 연구실(Marvelab)
Chap. 6 - 34