• 검색 결과가 없습니다.

Chapter 8 – 형 정의 , 구조형 및 공용형

N/A
N/A
Protected

Academic year: 2021

Share "Chapter 8 – 형 정의 , 구조형 및 공용형"

Copied!
52
0
0

로드 중.... (전체 텍스트 보기)

전체 글

(1)

Outline

8.1 형 정의 typedef 8.2 구조형 struct 8.3 구조형과 함수 8.4 공용형 union 8.5 비트 필드

8.6 요약

8.7 예제

(2)

• ( 예 8.1) typedef 정의와 선언

( 예 8.1) typedef

/* (1) 정의 */

typedef int BOOL;

typedef unsigned char TEXT;

typedef int INCHES, FEET, YARDS;

typedef int vector[10];

typedef char *string;

/* (2) 선언 */

BOOL flag; /* int flag; 와 같은 의미 */

TEXT buf[100]; /* unsigned char buf[100]; 와 같은 의미 */

INCHES length, width; /* int length, width; 와 같은 의미 */

vector a, b; /* int a[10], b[10]; 과 같은 의미 */

string text, input; /* char *text, *input; 과 같은 의미 */

<typedef 와 #define 의 차이점 >

- typedef 는 자료형에 대해서만 기호 이름을 부여 할 수 있다 .

- typedef 는 전처리기가 아닌 컴파일러에 의해 실행된다 .

(3)

• ( 예 8.2) typedef 의 사용 (1)

( 예 8.2)

typedef 의 사용

/* (1) 정의 */

#define N 3 /* 벡터 (vector) 와 행렬 (matrix) 의 크기 */

typedef double scalar;

typedef scalar vector[N];

typedef scalar matrix[N][N];

void add(a, b, c)

vector a, b, c; /* double a[3], b[3], c[3]; 과 같은 의미 */

{

int i;

for (i = 0; i < N; i++) a[i] = b[i] + c[i];

}

- 함수 add() 는 벡터를 연산하는 함수이다 .

- matrix 의 선언은 기 정의된 vector 를 사용하면 다음과 같이도 할 수 있다 .

typedef vector matrix[N];

(4)

• ( 예 8.3) typedef 의 사용 (2)

( 예 8.3)

typedef 의 사용

scalar dot_product(a, b) /* 벡터 a 와 벡터 b 의 내적 (dot product) */

vector a, b;

{

int i;

scalar s = 0;

for (i = 0; i < N; i++) s += a[i] * b[i];

return s;

}

void multiply(a, b, c) /* 행렬 곱셈 : a = b*c */

matrix a, b, c;

{

int i, j, k;

for (i = 0; i < N; i++) for (j = 0; j < N; j++)

for (c[i][j] = 0, k = 0; k < N; k++) c[i][j] += a[i][k] * b[k][j];

}

- 벡터의 내적 구하는 dot_product 와 두 행렬의 곱을 계산하는 multiply - scalar, vector 의 정의는 예 8.2 에서 정의

- matrix a, b, c; 는 double a[N][N], b[N][N], c[N][N]; 과 동일 .

(5)

• 구조형 struct 의 형식

– (1) 새로운 구조형의 정의

– (2) 이미 정의된 struct 태그명 형의 변수를 선언 – (3) 새로운 구조형을 정의하고 , 해당 변수도 선언함

(1) struct 태그명 { 항목 _ 선언 _ 리스트 };

(2) struct 태그명 식별자명 [, 식별자명 … ];

(3) struct [ 태그명 ] { 항목 _ 선언 _ 리스트 } 식별자명 [, 식별자명 … ];

- 태그명 은 식별자이다 .

- 태그명 은 구조형의 template 명이라고도 한다 .

- [ ] 안의 것은 생략 가능하다는 의미임 .

(6)

• ( 예 8.4) 구조형 struct 예 (1)

• 형식 3 을 이용하여 태그명 이 tg 인 struct 를 정의하고 , struct tg 형의 변수 y 를 선언한다 .

• struct tg 에는 4 개의 멤버가 있다 .

( 예 8.4) struct 예

struct tg { short a;

int b;

char c;

char d[4];

} y;

• 형식 2 를 이용하여 struct tg 형의 변수 w, x, z 를 추가로 선언한다 .

struct tg w, x, z;

(7)

• ( 예 8.5) 구조형 struct 예 (2)

• (1) 은 3 학생의 레코드를 표현하기 위해 s1, s2, s3 를 구조형 변수로 선언하고 있으나 , 구조체의 태그명 이 없으므로 다른 곳에 서 추가적인 학생 레코드의 선언이 가능하지 않다 .

( 예 8.5) struct 예

/* (1) */

struct {

long student_id; /* 학번 */

char *student_name; /* 학생 이름 */

char grade; /* 성적 */

} s1, s2, s3;

(8)

• ( 예 8.5) 구조형 struct 예 (2)

• (2) 에서는 구조체의 태그명 으로 student 를 사용하였으나 , 변 수 선언은 없다 .

• (3) 과 같이 하면 , 비로소 변수들을 위한 기억장소가 할당된다 .

( 예 8.5) struct 예

/* (2) */

struct student {

long student_id; /* 학번 */

char *student_name; /* 학생 이름 */

char grade; /* 성적 */

};

/* (3) */

struct student temp, class[100];

struct student {

long student_id; /* 학번 */

char *student_name; /* 학생 이름 */

char grade; /* 성적 */

} temp, class[100];

• (2)(3) 을 결합시켜 다음과 같이 사용할 수 있다 .

(9)

• ( 예 8.6) typedef 로 구조형 선언

• 다음의 변수 c 는 구조형 배열이다 .

• complex 를 struct 구문 대신 사용할 수 있다 .

( 예 8.6) typedef 로 구조형 선언

typedef struct {

float re; /* 실수부 */

float im; /* 허수부 */

} complex;

complex a, b, c[100];

(10)

• ( 예 8.6 계속 ) typedef 로 구조형 선언

• [ 기억 장소 할당 형태 ]

( 예 8.6 계속 )

c[0].re c[0].im

re im

float Çü float Çü

re im

a 또는 b

c[0]

c[1].re c[1].im

c[99].re c[99].im

c[1]

c[2]

c[99]

멤버 연산자

(11)

• 구조형 원소의 접근

구조형 _ 변수명 . 멤버명

• ( 예 8.7) 구조형 멤버의 접근

• 예 8.4, 8.5, 8.6 의 구조형 멤버에 대한 값 배정

• 구조형 배열의 각 원소의 멤버 접근 법 : c[4].im

• 멤버 자체가 배열형 자료인 경우 : y.d[0]

y.a = 1;

y.b = 623596;

y.c = ‘A’;

y.d[0] = ‘T’;

y.d[1] = ‘A’;

y.d[2] = ‘N’;

y.d[3] = ‘K’;

temp.grade = ‘A’;

temp.student_name = “Chanho Park”;

temp.student_id = 90118;

c[0].re = 12.06;

c[0].im = 3.0;

c[4].re = 18.09;

( 예 8.7)

구조형 멤버의 접근

(12)

• ( 예 8.8) 구조형 멤버를 접근하는 프로그램

– class 가 구조형 배열이다 . 즉 class 의 각 원소는 구조형이다 . – 각 구조형 원소의 멤버 grade 가 ‘F’ 면 cnt 를 증가시킨다 .

/* F 학점 받은 학생수를 반환하는 함수 */

int fail_count(struct student class[]) {

int i, cnt = 0;

for (i = 0; i < NOSTUDENTS; i++) cnt += class[i].grade == ‘F’;

return cnt;

}

( 예 8.8)

구조형 멤버를

접근하는 프로그램

(13)

• ( 예 8.9) 구조형의 내포와 참조

– 구조형 변수 x 의 멤버 z 가 구조형이므로 x.z.s 같이 참조 ( 즉 접근 ) 한다 .

struct tgy { char cbuf[10];

struct tgz { int i;

short s;

} z;

int t;

} x;

. . . x.z.s = 1;

. . .

( 예 8.9)

구조형의 내포와

참조

(14)

• ( 예 8.10) 구조형의 초기화

– 구조형의 멤버보다 작은 수의 값이 할당되면 나머지는 0 으로 간주된다 .

/* (1) */

complex m[3][3] = {

{{1.0, -0.5}, {2.3, 1.0}, {0.7, 0.7} }, /* m[0][] 부분 */

{{7.0, -6.5}, {-0.5, 1.0}, {45.7, 8.0} }, /* m[1][] 부분 */

} /* m[2][] 은 생략되었으므로 0 으로 배정됨 */

/* (2) */

static struct month { char *mname;

int day;

} month_tab[] = {

“January”, 31, “February”, 28,

“March”, 31, “April”, 30,

“May”, 31, “June”, 30,

“July”, 31, “August”, 31,

“September”, 30, “October”, 31, “November”, 30, “December”, 31 };

( 예 8.10)

구조형의 초기화

(15)

• ( 예 8.10 계속 ) 구조형의 초기화

– (2) 는 다음과 동일하다 .

/* (2)’ */

static struct month { char *mname;

int day;

} month_tab[] = {

{“January”, 31}, {“February”, 28}, {“March”, 31}, {“April”, 30},

{“May”, 31}, {“June”, 30},

{“July”, 31}, {“August”, 31}, {“September”, 30}, {“October”, 31}, {“November”, 30}, {“December”, 31} };

( 예 8.10 계속 )

구조형의 초기화

(16)

• struct 형에 대한 포인터

– 구조형 포인터가 구조형 보다 다루기 편리한 경우 있음 – 구조형 포인터를 인수로 사용

• 구조형을 전달할 수 없는 C 컴파일러도 있다 .

• 포인터를 넘기면 구조형의 복사가 일어나지 않아 메모리를 절약

• 구조형의 멤버로 다른 구조형을 가리키는 포인터를 사용하면 편리하다 .

– ( 예 8.11) struct 형에 대한 포인터 선언

/* ( 예 8.11) */

struct e { int n;

int k;

double s;

};

/* struct e 형의 배열 a[] 를 선언하고 초기화 */

static struct e a[] = { {1, 5, 1.7691}, {2, 6, 3.5512}, {3, 6, 7.1545} };

struct e *p; /* (1) */

p = a;

( 예 8.11)

구조형의 포인터

(17)

– ( 예 8.11 계속 ) struct 형에 대한 포인터 선언

• struct e *p;

– p 를 struct e 포인터 변수로 선언한다 .

• p = a;

– 배열 a 의 주소 즉 &a[0] 를 p 에 저장함 – 이제 p -> n 으로 a[0].n 을 접근할 수 있다 .

• p++;

– 이제 p 는 &a[1] 과 같다 .

– 이제 p -> n 은 a[1].n 과 같다 .

( 예 8.11 계속 ) 구조형의 포인터

p - > n

p - > s p - > k p

포인터 변수

p++

p++

a[0].n a[0].k a[0].s

(18)

– ( 예 8.12) 간접 멤버 연산자 -> 의 사용 예

• 구조형 포인터 변수 p 에 구조형 변수 temp 의 포인터를 배정하 여 사용하고 있다 .

• p -> grade 는 p 가 가리키는 구조형의 멤버 grade 를 뜻함 .

/* ( 예 8.12) */

struct student temp, *p = &temp;

temp.grade = ‘A’;

temp.student_name = “Chanho Park”;

temp.student_id = 90118;

( 예 8.12) -> 의 사용

수 식 연산 우선 순위 결 과

temp.student_name temp.grade temp.student_id

(*p) ->

student_name+2

*p ->

student_name+2

*(p ->

student_name+2)

p -> student_name p -> grade p -> student_id

*((*p) ->

student_name) + 2

*(p -> student_name) + 2

p -> student_name [2]

Chanho Park A

90118 /* 에러 */

E

a

(19)

– ( 예 8.13) 함수에 구조형 멤버 자료 전달

• 구조형 멤버를 인수로 : 인수가 복사되어 call by value 로 동작

• 구조형 멤버의 포인터를 인수로 :

– 앞에 & 를 붙여 주소를 넘김 : call by reference 의 효과 – 주소 연산자 & 는 멤버 앞이 아니라 구조형의 이름 앞에 쓴다 .

• [ 주의 ] 문자열 s 는 자체가 주소를 의미한다 .

/* (1) */

struct fred { char x;

int y;

char s[10];

} mike;

/* (2) */

func1(mike.x); /* x 의 문자값 전달 */

func2(&mike.x); /* 문자형 x 의 주소 전달 */

func3(mike.y); /* y 의 정수값 전달 */

func4(&mike.y); /* 정수형 y 의 주소 전달 */

func5(mike.s); /* 문자열 s 의 주소 전달 */

func6(mike.s[2]); /* s[2] 의 문자값 전달 */

func7(&mike.s[2]); /* 문자형 s[2] 의 주소 전달 */

( 예 8.13) 함수에

구조형 멤버

자료 전달

(20)

– ( 예 8.14) 함수에 구조형 전체를 전달 (1)

( 예 8.14) 함수에 구조형 전체를 전달

1 /* File : prog8-14.c

2 함수에 구조형 전체를 전달 (1) */

3 #include <stdio.h>

4 int main(void) 5 {

6 struct { 7 int a, b;

8 char ch;

9 } arg;

10 void f1();

11 arg.a = 1000;

12 f1(arg);

13 } 14

(21)

– ( 예 8.14) 함수에 구조형 전체를 전달 (1)

• 실 매개변수 (arg) 와 형식 매개 변수 (parm) 을 같은 구조형으로 선언 .

• 인수 선언시 struct 를 선언하는 방식으로 컴파일러에 따라 Warning 메시지를 주기도 함

( 예 8.14 계속 ) 함수에 구조형

전체를 전달

output

15 void f1(parm) 16 struct {

17 int x, y;

18 char ch;

19 } parm;

20 {

21 printf(“%d\n”, parm.x);

22 }

1000

(22)

– ( 예 8.15) 함수에 구조형 전체를 전달 (2)

– ( 예 8.14) 대신 이 방법을 사용하시오 !!

– 동일한 struct 형을 중복 선언하지 않는 버전

( 예 8.15) 함수에 구조형 전체를 전달

1 /* File : prog8-15.c

2 함수에 구조형 전체를 전달 (2) */

3 #include <stdio.h>

4 /* 구조형 형 정의 */

5 struct struct_type { 6 int a, b;

7 char ch;

8 };

9 int main(void) 10 {

11 struct struct_type arg; /* arg 선언 */

12 void f1();

13 arg.a = 1000;

14 f1(arg);

15 }

16 void f1(parm)

17 struct struct_type parm;

18 {

19 printf(“%d\n”, parm.a);

20 }

(23)

• 포인터 기반 함수와 구조형 기반 함수

– 다음 구조형을 정의하여 사용하자 .

헤더 file complex.h

1 /* File : complex.h

2 For prog8-16.c & prog8-17.c */

3 typedef struct { 4 float re;

5 float im;

6 } complex;

(24)

• ( 예 8.16) 포인터 기반 함수 ( 구조형 전달 ) 의 선언과 호출

– 다음 3 개의 함수를 포인터 인수를 사용하여 구현하자 .

• 복소수에 값을 배정하는 함수

• 두 개의 복소수를 더하는 함수

• 복소수를 출력하는 함수

( 예 8.16) 포인터 기반 함수

1 /* File : prog8-16.c

2 포인터 기반 함수 ( 구조형 전달 ) 의 선언과 호출 */

3 #include <stdio.h>

4 #include “complex.h”

5 void assign(complex *cp, float r, float i) 6 {

7 cp->re = r; /* (2) */

8 cp->im = i;

9 }

10 void add(complex *cp1, complex *cp2, complex *cp3) 11 {

12 cp3->re = cp1->re + cp2->re;

13 cp3->im = cp1->im + cp2->im;

14 } 15 16

(25)

17 void prnt(complex *cp) 18 {

19 printf(“%.3f + %.3f i\n”, cp->re, cp->im);

20 } 21

22 int main(void) 23 {

24 complex c1, c2, c3;

25 assign(&c1, 1.0, 2.0); assign(&c2, 3.0, 4.0);

26 add(&c1, &c2, &c3);

27 prnt(&c3);

28 }

• ( 예 8.16 계속 )

( 예 8.16 계속 )

output

4.000 + 6.000 i

(26)

• ( 예 8.17) 구조형 자료를 인수 및 반환값으로 사용

– 이것이 가능하지 않은 C 컴파일러도 있음 .

– 구조형이 값 호출 (call by value) 로 복사 (copy) 되어 전달 – 다음은 ( 예 8.16) 의 add2 는 add 를 재 작성한 버젼이다 .

• 계산 결과를 구조체 (res) 에 저장하고 반환값으로 사용하였다 .

• main 에서 호출하는 부분 ( 줄 26) 도 바뀐다 .

( 예 8.17) 구조형 자체를 인수와 반환값으로 사용

호출 부분의 변경

1 /* File : prog8-17.c

2 구조형을 인수와 반환값으로 사용하는 add2 의 작성 */

. . . .

10 complex add2(complex c1, complex c2) 11 {

12 complex res; /* 계산 결과를 저장 */

13 res.re = c1.re + c2.re;

14 res.im = c1.im + c2.im;

15 return res;

16 }

26 c3 = add2(c1, c2);

(27)

• ( 예 8.18) 공용형 자료 정의

– n 은 int 형이므로 통상 4 바이트 , x 는 double 형이므로 통상 8 바이트 , c 는 char 형이므로 통상 1 바이트가 필요함 .

– union 의 멤버들 (n, x, c) 은 기억장소를 공유한다 .

– 따라서 멤버 중 가장 큰 메모리를 필요로 하는 멤버 x 가 필요한 공 간 (8 바이트 ) 을 확보한다 .

– 모든 멤버 중 단 한 개만 사용하는 경우 ( 가령 심볼 테이블 등 ) 공 간 절약을 위해 흔히 사용된다 .

( 예 8.18) union

/* ( 예 8.18) */

union ifc { int n;

double x;

char c;

} temp;

temp.c temp.n

temp.x

(28)

• ( 예 8.19) 공용형 자료 정의

– union 과 struct 의 차이점은 union 의 멤버들은 모두 같은 주소에 배정된다는 점이다 . union 은 공간을 절약할 수 있다 .

– union ifc 의 3 멤버는 주소가 같으므로 , 가령 temp.n 에 저장 후 , temp.x 에 저장하면 temp.n 의 원래 값은 엉뚱한 값이 됨 . – union 멤버의 접근 방법은 struct 와 동일하다 .

( 예 8.19) union 변수의 선언과 참조

/* ( 예 8.19) */

union ifc fit;

union ifc save[10]; /* 10 개의 공용형 변수 배열 */

union ifc *pu; /* union ifc 형 자료에 대한 포인터 변수

temp.n = 444; /* ( 예 8.18) 에서 정의된 변수 temp 의 멤버값 배정 */

temp.x = 15.9;

temp.c = ‘H’;

fit.n = 23;

fit.x = 2.0;

fit.c = ‘a’;

pu = &fit;

k = pu -> n; /* k = fit.n 과 같음 */

(29)

• ( 예 8.20) 구조형과 공용형의 혼용

– union fromwhere 은 foreign_traveller 와 korean_traveller 라는 멤버를 가진다 .

– 이 두 멤버는 동시에 사용되지 않으므로 공용형 멤버로 정의 되었다 .

( 예 8.20) struct 와 union 의 혼용

/* ( 예 8.20) */

struct foreign_traveller { int country_code;

int city_code; *pc;

char passport_id[20];

};

struct korean_traveller { int district_code;

char resident_id[13];

};

union fromwhere {

struct foreign_traveller f_trav;

struct korean_traveller k_trav;

};

(30)

• ( 예 8.20 계속 ) 구조형과 공용형의 혼용

– traveller_record 란 구조형의 한 멤버로 union fromwhere 형을 사용하고 있다 .

( 예 8.20 계속 )

/* ( 예 8.20 계속 ) */

typedef struct { int serial_no;

char name[10];

short iskorean;

union fromwhere a;

} traveller_record;

(31)

• ( 예 8.21) 비트 필드 (bit field) 의 사용

– 1 또는 0 의 값 만을 갖는 비트 단위로 정의 가능

– (1) (1/0 저장 가능한 ) 1 비트짜리 멤버 3 개로 이루어진 struct – (2) ( 문자 저장 가능한 ) 8 비트짜리 멤버 4 개로 이루어진 struct

( 예 8.21) 비트 필드 선언

비트 필드의 접근

/* ( 예 8.21) 비트 필드의 사용 */

/* (1) */

struct {

unsigned class_a : 1;

unsigned class_b : 1;

unsigned class_a : 1;

} fig;

/* (2) */

struct word_bytes {

unsigned byte0 : 8, byte1 : 8, byte2 : 8, byte3 : 8;

} y;

1 비트 1 비트 1 비트

class_a class_b class_c

fig.class_a = 1;

y.byte3 = ‘w’;

(32)

• ( 예 8.22) 마스크 사용 비트 처리

– 시스템에 따라 비트 필드를 사용하면 효율이 떨어질 수 있다 . – 특정 비트의 마스크를 이용한 방법이 일반적인 방법임 .

– 01, 02, 04 와 같이 맨 앞에 0 을 붙이면 8 진법 숫자임 . – (1) 정수 fig 의 0 번째 비트를 1 로 set 시킴 .

– (2) 정수 fig 의 1 번째 비트가 0 인지 테스트 함

(fig & BIT1) 은 fig 의 해당 비트가 1 이면 참 (1), 0 이면 거짓 (0) 임

( 예 8.22) 마스크 사용 비트 처리

/* ( 예 8.22) 마스크 사용 비트 처리 */

#define BIT0 01 #define BIT1 02 #define BIT2 04 int fig;

. . . . .

fig |= BIT0; /* (1) */

if ((fig & BIT1) == 0) /* (2) */

. . . . .

(33)

예제 8.1

[ 해 설 ]

/* 예제 8.1 다음 선언들의 의미는 ? */

/* (1) */

typedef int WHOLE;

/* (2) */

typedef struct club { char name[30];

int size, year;

} GROUP;

/* (3) */

typedef GROUP, *PG;

/* (4) */

typedef void DRAW(int, int);

- (1) WHOLE 은 int 형과 동의어로 정의된다 .

- (2) 3 개의 멤버를 가진 struct club 을 선언하고 , GROUP 를 그와 동의어 로 정의한다 .

- (3) PG 는 기 정의된 GROUP 포인터 형라고 정의 된다 .

- (4) 정수 2 개를 인수로 취하고 반환형이 없는 함수에 대한 형 정의이다 .

- DRAW box; 는 void box(int, int); 와 같은 선언이 된다 .

(34)

예제 8.2

[ 해 설 ]

/* 예제 8.2 다음 선언들의 의미는 ? */

/* (1) */

struct {

float x, y;

} complex;

/* (2) */

struct { float x, y;

} complex[100];

/* (3) */

struct employee { char name[20]

int id;

long class;

} temp;

- (1) complex 라는 구조형 변수를 정의함 . 그 구조형은 float 형 x, y 를 멤버로 갖으나 , 태그가 없다 .

- (2) 구조형의 배열 선언 . 각 원소는 2 개의 멤버를 가진 구조형이다 .

- (3) temp 라는 구조형 변수 선언 . 구조형의 멤버는 name, id, class 이

다 .

(35)

예제 8.2( 계속 )

[ 해 설 ]

/* 예제 8.2( 계속 ) */

/* (4) */

struct employee student, faculty, staff;

/* (5) */

struct sample { char c;

float *pf;

struct sample *next;

} x;

/* (6) */

struct {

unsigned icon : 8;

unsigned color : 4;

unsigned underline : 1;

unsigned blink : 1;

} screen[25][80];

- (4) 변수 student, faculty, staf 를 struct employee 형으로 선언 - (5) 구조형의 3 째 멤버 next 는 동일한 구조형 자료에 대한 포인터이다 . - (6) screen 이라는 이름의 구조형 배열로 원소는 2000 개이다 .

각 원소는 4 개의 멤버로 구성되고 , 각 멤버는 각각 길이가 8 비트 ,

4 비트 , 1 비트 , 1 비트이다 .

(36)

예제 8.3

[ 해 설 ]

/* 예제 8.3 다음 문장들의 의미는 ? */

struct rec { int a;

struct rec *sp;

} item, list[5];

/* (1) */

item.a = 10;

/* (2) */

list[0].sp = &list[1];

list[0].sp -> a = 20;

/* (3) */

list[3].a = 30;

- (1) struct rec 형의 변수 item 의 멤버 a 에 10 을 배정한다 .

- (2) 배열 list 의 0 번째 원소의 멤버 sp 의 값으로 list[1] 의 포인터를 저 장 .

이후 그 포인터가 가리키는 구조체 ( 즉 list[1]) 의 멤버 a 에 20 을 저 장 .

- (3) 구조형의 배열로부터 , 각 구조형 원소의 멤버에 접근하는 방법 .

(37)

예제 8.4

5 CMPLX {

6 double re;

7 double im;

8 };

9 int main(void) 10 {

11 static CMPLX za = {3.0, 4.0};

12 static CMPLX zb = {5.0, 6.0};

13 CMPLX z, cadd(), cmult(); void cprint();

14 z = cadd(za, zb); cprint(z);

15 z = cmult(za, zb); cprint(z);

16 }

17 /* --- 복소수 덧셈 --- */

18 CMPLX cadd(CMPLX za, CMPLX zb) 19 {

20 CMPLX z;

21 z.re = za.re + zb.re;

22 z.im = za.im + zb.im;

23 return z;

24 }

(38)

예제 8.4( 계 속 )

[ 해 설 ]

output

8.000 + 10.000 i -9.000 + 38.000 i

- 줄 4 로 CMPLX 를 struct complex 와 같게 선언함 .

- 복소수를 실수부 re(real) 와 허수부 im(imaginary) 로 구성된 구조형 으로 정의 .

- 두 복소수의 합과 곱을 구하는 프로그램

29 z.re = za.re * zb.re - za.im * zb.im;

30 z.im = za.re * zb.im + za.im + zb.re;

31 return z;

32 }

33 /* --- 복소수 출력 --- */

34 void cprint(CMPLX z) 35 {

36 printf(“%.3f + %.3f i\n”, z.re, z.im);

37 }

(39)

예제 8.5

[ 해 설 ] output

5 {

6 static struct s1 { 7 char c[4], *s;

8 } s1 = {“abc”, “def” };

9 static struct s2 { 10 char *cp;

11 struct s1 ss1;

12 } s2 = {“ghi”, { “jkl”, “mno” }};

13 printf(“s1.c[0]=%c\t”, s1.c[0]);

14 printf(“*s1.s=%c\n”, *s1.s);

15 printf(“s1.c=%s\t”, s1.c);

16 printf(“s1.s=%s\n”, s1.s);

17 printf(“s2.cp=%s\t”, s2.cp);

18 printf(“s2.ss1.s=%s\n”, s2.ss1.s);

19 printf(“++s2.cp=%s\t”, ++s2.cp);

20 printf(“++s2.ss1.s=%s\n”, ++s2.ss1.s);

21 }

s1.c[0]=a *s1.s=d s1.c=abc s1.s=def s2.cp=ghi s2.ss1.s=mno ++s2.cp=hi ++s2.ss1.s=no

- struct 의 멤버로 struct 를 사용할 수 있다 .

(40)

예제 8.6

struct 의 포인터를 인 수로 사용

5 char name[20];

6 int id;

7 } student = { “Kim”, 73 };

8 int main(void) 9 {

10 int id, match();

11 char *name1 = “Lee”, *name2 = “Kim”;

12

13 if (id = match(&student, name1))

14 printf(“%s’s ID is %d.\n”, name1, id);

15 else

16 printf(“He is not %s.\n”, name1);

17

18 if (id = match(&student, name2))

19 printf(“%s’s ID is %d.\n”, name2, id);

20 else

21 printf(“He is not %s.\n”, name2);

22 }

23 int match(struct student *r, char *n) 24 {

25 if (strcmp(r->name, n) == 0) 26 return r->id;

27 return 0; /* 실패 */

28 }

(41)

예제 8.6( 계속 ) [ 해 설 ]

output

He is not Lee.

Kim’s ID is 73.

정의된 자료형을 갖는 변수도 student 로 정의하고 , 그 멤버값을 “ Kim” 과 73 으로 초기화 한다 .

- 줄 13 과 줄 18 에서는 각각 변수 student 에 저장된 name 이 “Lee” 인지 또는 “ Kim” 인지 확인하고 있다 .

확인이되면 해당 학생의 id 가 반환된다 .

- 함수 match 는 첫 인수가 가리키는 구조체의 멤버 name 이 가리키는 이름이 둘째 인수와 같은지 strcmp 함수를 호출하여 알아보고 ,

맞으면 해당 학생의 id 를 반환한다 . 아니면 0 을 반환한다 . - strcmp 함수는 비교하는 두 문자열이 같으면 0 을 반환함에 주의 .

- 줄 26 의 r->id 는 포인터 r 이 가리키는 구조체의 멤버 id 를 의미함 .

(42)

예제 8.7

[ 해 설 ]

static int add(int x, int y) {

return (x+y);

}

/* (2) */

typedef struct { char name[20];

int id;

} STUDENT;

/* --- */

STUDENT frontstu (STUDENT a, STUDENT b) {

return ((a.id < b.id) ? a : b);

}

- (1) 함수 add() 는 int 형 자료를 반환하는 함수이다 .

static 지정으로 이 함수는 같은 원시 file 내에서만 호출할 수 있다 . static 을 생략한 일반함수는 외부함수로 다른 file 에서도 호출 가능 . - (2) id 등의 멤버를 갖는 구조체를 STUDENT 라고 정의함 .

함수 frontstu 는 인수로 넘어온 STUDENT 형 두 인수의 id 를 비교 하여

그 값이 작은 인수를 반환한다 .

(43)

예제 8.7( 계속 )

[ 해 설 ]

/* 예제 8.7( 계속 ) */

/* (3) */

char *shortername_stu(s1, s2) char s1[], s2[];

{

int i;

i = 0;

while (s1[i] != ‘\0’ && s2[i] != ‘\0’) i++;

if (s1[i] == ‘\0’) return s1;

return s2;

}

- (3) 문자배열에 대한 포인터를 반환하는 함수 .

두 인수가 가리키는 문자열 중 길이가 짧은 문자열의 포인터를 반환 .

(44)

예제 8-8

5 int id;

6 char name[10];

7 };

8

9 void st_copy(struct st *s1, struct st *s2) 10 {

11 int j;

12 s1 -> id = s2 -> id;

13 for (j = 0; j < 10; j++)

14 s1 -> name[j] = s2 -> name[j];

15 }

16 void st_print(struct st *s) 17 {

18 printf(“ 번호 = %d, 이름 = %s\n”, s -> id, s -> name);

19 } 20

(45)

예제 8-8( 계속 )

output

25 printf(“ 학생 1 : ”); st_print(&std1);

26 printf(“ 학생 2 : ”); st_print(&std2);

27 st_copy(&std1, &std2);

28 printf(“\n 학생 2 의 정보를 학생 1 로 복사한다 .\n\n”);

29 printf(“ 학생 1 : ”); st_print(&std1);

30 printf(“ 학생 2 : ”); st_print(&std2);

31 }

학생 1 : 번호 = 30, 이름 = Kim 학생 2 : 번호 = 70, 이름 = Lee 학생 2 의 정보를 학생 1 로 복사한다 .

학생 1 : 번호 = 70, 이름 = Lee 학생 2 : 번호 = 70, 이름 = Lee

- st_copy(&std1, &std2); 는 std2 가 가리키는 구조체를 std1 이 가 리키는 구조체에 복사한다 .

- main 에서는 구조체 복사 (copy) 전과 후의 모습을 확인한다 .

(46)

예제 8-9(1)

[ 해 설 ]

output

5 int i, j, k;

6 float m[2][3];

7 } x = { 1, 2, 3, {4.0, 5.0, 6.0} };

8

9 int main(void) 10 {

11 printf(“%d\t%.3f\t%.3f\n”, x.j, x.m[0][1], x.m[1][1]);

12 }

2 5.000 0.000

- x 의 int 형 멤버 x, y, z 는 1, 2, 3 으로 초기화된다 .

- x 의 float 형 배열 m 의 첫 행의 3 원소들 m[0][0], m[0][1], m[0][2] 는 4.0, 5.0, 6.0 으로 초기화된다 .

- 값이 제공되지 않은 2 째 행의 3 원소들 m[1][0], m[1][1], m[1]

[2] 는 0 으로 초기화 된다 .

(47)

예제 8-9(2)

[ 해 설 ]

output

5 char x[2][3];

6 int i, j, k;

7 } y;

8

9 int main(void) 10 {

11 y.i = 0;

12 y.x[1][0] = ‘4’;

13 printf(“%d\t%d\t%d\n”, y.I, y.j, y.k);

14 }

52 52 52

- 공용형의 4 멤버 중 x 는 6 바이트 , 나머지 i, j, k 는 4 바이트 필요 하므로 이 공용형은 총 6 바이트 차지함

- 문자 ‘ 4’ 는 코드값이 52 이다 .

- 정수는 x[0][0], x[0][1], x[0][2],x[1][0] 과 겹친다 .

- 정수 4 바이트 중 가장 작은 수를 저장하는 바이트가 x[1][0] 인 기계의 경 우는 아래와 같이 i 값 , j 값 , k 값이 52 이다 .

- 정수 4 바이트 중 가장 작은 수를 저장하는 바이트가 x[0][0] 인 기계의 경

우는 매우 큰 값 (52 * 2

24

= 872415232) 이 출력된다 .

(48)

예제 8.10

[ 해 설 ]

/* 예제 8.10 다음 선언들의 의미는 ? */

/* (1) */

union sign { int svar;

unsigned uvar;

double dvar;

} number;

/* (2) */

union { struct { char icon;

unsigned color:4;

} window1, window2, window3, window4;

} screen[25][80];

- (1) int 형 , unsigned 형 및 double 형 멤버 3 개 중 가장 큰 메모리 를 필요로 하는 double 형 ( 통상 8 바이트 ) 크기를 갖는 공용형 sign 을 선언하고 그 변수 number 를 정의함

- (2) 공용형 원소 2000 개를 갖는 2 차원 배열 screen 의 선언이다 . 각 원

소는 4 개의 멤버 window1, … window4 중 한 개를 가진다 .

(49)

예제 8-11

5 int n;

6 float x;

7 } number;

8

9 int main(void) 10 {

11 number temp;

12 temp.n = 3;

13 printf(“%d %f\n”, temp.n, temp.x);

14 temp.x = 3.0;

15 printf(“%d %f\n”, temp.n, temp.x);

16 }

3 0.000000

1077936128 3.000000

- 공용형의 두 멤버가 동일한 주소를 갖는다는데 주의하라 .

- 값을 배정한 멤버와 접근하는 멤버가 달라도 에러로 처리되지않음 .

- 올바른 사용은 전적으로 프로그래머의 책임이다 .

(50)

예제 8.12

[ 해 설 ]

/* 예제 8.12 다음 선언들의 의미는 ? */

/* (1) */

struct both { int a;

char b;

} (*var[ ]) (struct both, struct both);

/* (2) */

union sign { int x;

unsigned y;

} **var[5][5];

/* (3) */

union sign *(*var[5])[5];

- (1) struct both 형의 2 인수를 받아 struct both 형을 반환하는 함수 의 포인터들의 배열

- (2) union sign 포인터에 대한 포인터들의 배열의 배열

- (3) union sign 포인터들의 배열에 대한 포인터들의 배열

(51)

예제 8.13

[ 해 설 ]

/* 예제 8.13 다음 구조형 선언의 기억 형태는 ? */

struct {

unsigned icon:8;

unsigned color:4;

unsigned underline:1;

unsigned blink:1;

} screen[25][80];

- screen 의 2000 개 원소 중 첫 번째 원소의 저장 모습이다 . 14 비트 크기 임 .

screen[0][0]

underline 원소

color 원소

icon 원소 blink 원소

(52)

예제 8-14

output

5 {

6 struct {

7 unsigned carry: 2; /* overflow */

8 unsigned parity: 2; /* 1 = 짝수 ; 0 = 홀수 */

9 unsigned acarry: 2; /* 보조 carry */

10 unsigned zero: 1; /* 결과가 0 */

11 unsigned sign: 1; /* 결과가 음수 */

12 } f8080;

13 f8080.carry = f8080.acarry = f8080.sign = 0;

14 f8080.parity = f8080.zero = 1;

15 if (f8080.carry == 0) printf(“carry 없음 \n”);

16 if (f8080.parity == 0) printf(“ 짝수 parity\n”);

17 if (f8080.acarry == 0) printf(“ 보조 carry 없음 \n”);

18 if (f8080.zero == 0) printf(“ 결과가 0 이 아님 \n”);

19 if (f8080.sign == 0) printf(“ 결과가 양수임 \n”);

20 }

carry 없음 보조 carry 없음 결과가 양수임

참조

관련 문서

- 자유주의와 부르주아의 권력 도전을 방어 - 노동계급의 사회주의적 저항과 혁명을 방지 국가가 노동계급의 복지제공자 역할 수행 노동자는 군주에게

양궁선수와

- TCP는 흐름 제어와 오류 제어를 구별한다. - 이 절에서는 오류 제어를 무시하고 흐름 제어에

File[] listFiles() : 해당 경로에 있는 파일의 목록을 File 배열로 리턴합니다.. String getName() : 해당 경로에 있는 파일이나

• 모든 자바 입출력 클래스는 궁극적으로 바이트단위 입출력 을

™ 정적 링크 (Static link) Return address Access link. ™ 비지역변수

첫 번째 worker 함수 호출 10번 결과를 출력. 두 번째 worker 함수 호출

내부유동에서의 속도분포로부터 평균속도를, 온도분포로부터 평균온도를