구조체와포인터 -...

15
Intelligence Networking and Computing Lab. 구조체와 포인터 - 1 부산대학교 전기컴퓨터공학부 김종덕 ([email protected]) 본 강의 자료는 문정욱 교수님의 강의 자료를 활용하여 작성하였습니다.

Transcript of 구조체와포인터 -...

Page 1: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

Intelligence Networking and Computing Lab.

구조체와 포인터 - 1

부산대학교 전기컴퓨터공학부

김종덕 ([email protected])

본 강의 자료는 문정욱 교수님의 강의 자료를 활용하여 작성하였습니다.

Page 2: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

구조체란?

❖ 예: 학생관리 프로그램의 각 학생에 대

한 기록(record)

▪ 한 학생에 대한 자료들을 한 곳에 모아서 관

리하면 편리

▪ 한 학생의 이름, 학번, 나이, 전화번호, 전공 등

❖ 구조체는 여러 자료형 변수들의 집합

체이다.

❖ C의 구조체 구문 구조

▪ 요소(Element), 멤버(Member)/필드(Field)

▪ 구조체를 구성하는 변수

❖ 구조체는 새로운 자료형(Type)의 하나

❖ C의 구조체 정의 및 활용 예 1

2

struct Declaration :

struct name(optional) {type1 member1;type2 member2;...typen membern;

};

#include <stdio.h>int main(void){

struct student {int id;char *pname;double points;

};

struct student s1, s2;

s1.id = 1;s1.pname ="Choi";s1.points = 9.9;

s2.id = 2;s2.pname ="Park";s2.points = 0.1;

printf("[%d:%s] = %lf\n", s1.id,s1.pname, s1.points);

printf("[%d:%s] = %lf\n", s2.id,s2.pname, s2.points);

return 0;}

새로운 Type을 선언하는 것

새로운 Type의 이름은?

변수의 선언

구조체에서 요소/멤버/필드를접근할 때는 ‘.’ 연산자를 사용

Page 3: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

Intelligence Networking and Computing Lab.

구조체 정의 및 변수 선언 방법 2

❖ 다음 A,B,C 3개의 코드는 본질적으로 동일함

▪ A는 구조체 정의선언과 해당 구조체 변수 선언을 분리한 것

▪ B는 구조체 정의선언과 해당 구조체 변수 선언을 동시에

▪ C는 구조체의 이름을 제거한 것

• 해당 구조체를 가지는 또 다른 변수를 선언 시에 불편할 수 있음

❖ 구조체를 큰 프로그램의 전반에서 사용할 경우 위와 같은 변수 선언

이 불편할 수 있음 이 경우 이후에 설명하는 typedef을 많이 사용3

#include <stdio.h>int main(void){

struct student {int id;char *pname;double points;

};

struct student s1, s2;

...}

#include <stdio.h>int main(void){

struct student {int id;char *pname;double points;

} s1, s2;

...}

#include <stdio.h>int main(void){

struct {int id;char *pname;double points;

} s1, s2;

...}

A B C

Page 4: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

Intelligence Networking and Computing Lab.

구조체의 활용

❖ Student 구조체의 print를 위해 별도의 함수를 만들기로 하고 좌측의 프로그램을 우

측과 같이 수정하였더니 Syntax Error가 발생하였다. 그 이유가 무엇일까?

❖ 해결책은?

4

#include <stdio.h>int main(void){

struct student {int id;char *pname;double points;

};

struct student s1, s2;

s1.id = 1;s1.pname ="Choi";s1.points = 9.9;

s2.id = 2;s2.pname ="Park";s2.points = 0.1;

printf("[%d:%s] = %lf\n", s1.id,s1.pname, s1.points);

printf("[%d:%s] = %lf\n", s2.id,s2.pname, s2.points);

return 0;}

#include <stdio.h>void print_student(struct student s){

printf("[%d:%s] = %lf\n", s.id, s.pname, s.points);

}int main(void){

struct student {int id;char *pname;double points;

};

struct student s1, s2;

s1.id = 1;s1.pname ="Choi";s1.points = 9.9;

s2.id = 2;s2.pname = "Park";s2.points = 0.1;

print_student(s1);print_student(s2);return 0;

}

Page 5: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

typedef

❖ typedef : Type에 별명(aliase)을 부

여하는 기능

❖ 주로 복잡한 type 이름을 간단하

게 표시하는 경우에 많이 사용

▪ 아래 코드는 unsigned int라는 type에

uint32라는 새로운 별명을 부여

▪ 배열에 대한 typedef도 가능함. 단 작성

방식에 유의할 것

❖ 구조체에 typedef이 많이 사용됨

5

int main(void){

typedef unsigned int uint32;typedef int * pint32;typedef int aint3[3];

unsigned int a; uint32 b;// T(a) == T(b)

int * pa;pint32 pb;// T(pa) == T(pb)

int aa[3]; aint3 bb;// T(aa) == T(bb)

}

#include <stdio.h>typedef struct student {

int id;char *pname;double points;

} STUD;

void print_student(STUD s){

printf("[%d:%s] = %lf\n", s.id, s.pname, s.points);

}int main(void){

STUD s1;struct student s2;

s1.id = 1;s1.pname ="Choi";s1.points = 9.9;

s2.id = 2;s2.pname = "Park";s2.points = 0.1;

print_student(s1);print_student(s2);return 0;

}

Page 6: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

Intelligence Networking and Computing Lab.

구조체 변수의 초기화

❖ 구조체 변수도 초기화 가능

▪ 배열의 초기화와 유사

▪ 멤버/필드 변수의 자료형과 초기화하는 값의 자료형은 일치하여야 함

6

typedef struct student {int id;char *pname;double points;

} STUD;

int main(void){

STUD s1 = {1, "Choi", 9.9};struct student s2 = {2, "Park", 0.1};. . .

}

Page 7: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

Intelligence Networking and Computing Lab.

구조체 변수에 대한 포인터

❖ 구조체 변수의 주소 값과 메모리 크기는 어떻게 될까?

❖ 구조체 변수에 대한 포인터와 관련 연산

7

typedef struct student {int id;char *pname;double points;

} STUD;

int main(void){

STUD s1 = {1, "Choi", 9.9};printf("%p, %d\n", &s1, sizeof(s1));. . .

}

int main(void){

STUD s1 = {1, "Choi", 9.9};STUD *pStudent = &s1;

*pStudent.id = 3; // Error(*pStudent).id = 4; // okpStudent->id = 5; // Good. . .

}

‘.’ 연산자의 우선 순위가 ‘*’연산자의 우선 순위 보다 높다.

연산자 사용방법 결과

. 구조체변수.요소/멤버/필드 요소/멤버/필드 변수

-> 구조체주소->요소/멤버/필드 요소/멤버/필드 변수

기능적으로는 문제가 없으나 연산자를 2개 사용

연산자를 하나만 사용하며 구조체 포인터에서 일반적으로 쓰임

Page 8: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

자료형과 메모리에 대한 이해

❖ 우측의 STUD와 STUD2는 같은

Member 또는 Element를 가지는 구조

체이나 그 순서에 차이가 있다.

❖ 어떤 컴퓨터에서 sizeof()를 이용하여

두 구조체의 크기를 비교하였더니 우

측 아래와 같이 STUD는 16Bytes,

STUD2는 24Bytes로 서로 다른 크기를

가진다.

❖ 이러한 구조체 크기 차이의 원인은 무

엇일까?

❖ 결과로부터 double 자료형은 어떤 메

모리 주소에서 시작할 수 있는지 유추

해보라

▪ 0x00000? : double의 경우 ?에 가능한 숫자는?

▪ int나 pointer 자료형은?

▪ short 자료형의 경우는?

8

typedef struct student {int id;char *pname;double points;

} STUD;

typedef struct student2 {int id;double points;char *pname;

} STUD2;

int main(void){

STUD s1 = {1, "Choi", 9.9};STUD2 s2 = {2, 0.1, "Park"};printf("%p, %d\n", &s1, sizeof(s1));printf("%p, %d\n", &s2, sizeof(s2));return 0;

}

0061FF20, 160061FF08, 24

출력 결과

Page 9: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

구조체 변수에 대한 Assignment 연산

❖ C 언어의 경우 배열에 대해서

Assignment를 할 수 없음 !!!

❖ 구조체 변수에 대해서 Assignment

를 할 수 있을까?

▪ 전통(?) C 언어에서는 지원하지 않았으

나 현재는 가능하며 실제 값들이

모두 복사된다.

• 메모리의 내용이 그대로 복사

• 허용되기는 하지만 남용하지 않아야 하

며 일반적인 경우 비추천

9

int main(void){

STUD s1 = {1, "Choi", 9.9};STUD s3;

s3 = s1; . . .

}

int main(void){

int aN1[]={1, 2, 3};int aN2[3];

aN2 = aN1;. . .

}

Page 10: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

Assignment 연산과 메모리 처리

❖ 1)의 = 연산은 실질적으로 몇 Byte

의 메모리 복사로 이어질까?

▪ sizeof(double) 8

❖ 2)의 = 연산은 실질적으로 몇 Byte

의 메모리 복사로 이어질까?

▪ sizeof(double *) 4

❖ 구조체 변수는 Assignment 가능

❖ 1)의 = 연산은 실질적으로 몇 Byte

의 메모리 복사로 이어질까?

▪ sizeof(STUD) 16

❖ 2)의 = 연산은 실질적으로 몇 Byte

의 메모리 복사로 이어질까?

▪ sizeof(STUD *) 4

10

int main(void){

STUD s1 = {1, "Choi", 9.9};STUD s3;STUD *ps;

s3 = s1; // 1)ps = &s1; // 2). . .

}

int main(void){

double d1 = 3.8;double d3;double *pd1;

d3 = d1; // 1)pd1 = &d1; // 2). . .

}

Page 11: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

Array and Pointer : ex) char str[] vs. char *str

❖ Case 1) 함수 내의 변수인 경우

▪ 아래에서 str1과 str2를 비교하라.

• 두 변수의 자료형은?

• 두 변수의 크기는?

▪ 두 변수는 동일한가?

▪ 아래와 같은 코드가 가능한가?

❖ Case 2) 함수 인자인 경우

▪ 아래 두 함수의 인자 char str[]과 char

*str은 실질적으로 동일하다 !!!

▪ 아래 코드는 문제 없이 동작

11

#include <stdio.h>int main(void){

char str1[] = "Hello";char *str2 = "Hello";. . .

}

#include <stdio.h>void print_str(char *str){

while (*str != '\0')putchar(*str++);

}void print_str2(char str[]){

while (*str != '\0')putchar(*str++);

}int main(void){

char str1[] = "Hello";print_str(str1);print_str2(str1);return 0;

}

#include <stdio.h>int main(void){

char str1[] = "Hello";while (*str1 != '\0')

putchar(*str1++);return 0;

} C 언어의 포인터는 어려워…

Page 12: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

구조체 변수와 함수의 인자

❖ 함수 인자의 관점에서 배열은 포

인터와 실질적/결과적으로 동일함!

▪ 배열의 경우 배열의 주소가 매개 변수

로 복사되는 것이며 배열이 새로운 배

열로 복사되는 것이 아님

❖ 구조체 변수와 함수의 인자?

▪ 우측의 코드에서 print_student()와

print_student2() 함수의 인자/매개변수

전달 과정을 비교해 보라.

12

#include <stdio.h>typedef struct student {

int id;char *pname;double points;

} STUD;

void print_student(STUD s){

printf("[%d:%s] = %lf\n", s.id, s.pname, s.points);

}

void print_student2(STUD *ps){

printf("[%d:%s] = %lf\n", ps->id, ps->pname, ps->points);

}

int main(void){

STUD s1 = {1, "Choi", 9.9};STUD s2 = {2, "Park", 0.1};

print_student(s1);print_student2(&s2);return 0;

}

Page 13: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

구조체 변수와 함수의 인자❖ 다음 코드에 대한 물음에 답하라

▪ 위 // 1)의 sum() 호출에 의해 배열 a의 내용이 변

하는가?

▪ 우측 // 3)의 print_student()에의해 구조체 s1의

내용이 변하는가?

▪ 우측 // 5)의 print_student2()에의해 구조체 s2의

내용이 변하는가?

❖ 다음 코드에 대해 물음에 답하라.

13

#include <stdio.h>int sum(int n[10]);

int main(void){

int a[10]={1,2,3,4,5,6,7,8,9,10};printf("Array Sum = %d\n",sum(a)); // 1)printf("Array Sum = %d\n",sum(a)); // 2)return 0;

}

int sum(int n[10]){

int i,s=0;for (i=0; i<10; i++) {

s = s+n[i];n[i] = s;

}return s;

}

#include <stdio.h>typedef struct student {

int id;char *pname;double points;

} STUD;void print_student(STUD s){

printf("[%d:%s] = %lf\n", s.id, s.pname, s.points);

s.id = 3;}void print_student2(STUD *ps){

printf("[%d:%s] = %lf\n", ps->id, ps->pname, ps->points);

ps->id = 4;}int main(void){

STUD s1 = {1, "Choi", 9.9};STUD s2 = {2, "Park", 0.1};print_student(s1); // 3)print_student(s1); // 4)print_student2(&s2); // 5)print_student2(&s2); // 6)return 0;

}

Page 14: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

Intelligence Networking and Computing Lab.

구조체 변수와 함수의 인자

❖ C언어에서 구조체 변수와 배열 변수의 대입 및 함수 인자 처리 과정

에 차이가 있음에 유의하라

▪ 초창기 C 언어의 경우 구조체 변수 역시 배열 변수와 유사한 제약이 있었음

❖ 메모리 복사는 CPU의 효율을 떨어뜨리는 연산임

▪ 메모리 복사를 줄이는 것이 좋음

❖ 구조체 변수를 인자로 할 경우 “구조체 복사”가 좋을까? 아니면 “구

조체 포인터” 사용이 좋을까?

▪ 포인터의 경우 메모리 복사 부하를 최소화하는 장점

• 다만 함수 내에서 원하지 않는 구조체 내용 변경 등의 Side Effect가 발생할 수도 있음

14

Page 15: 구조체와포인터 - keris2.dl.cdn.cloudn.co.krkeris2.dl.cdn.cloudn.co.kr/KOCW/document/2016/... · Intelligence Networking and Computing Lab. 구조체정의및변수선언방법2

Intelligence Networking and Computing Lab.

구조체의 배열

❖ 구조체에 대한 배열도 가능함. 구조체 배열 변수와 그 초기화 예

15

#include <stdio.h>typedef struct student {

int id;char *pname;double points;

} STUD;

void print_student(STUD s){

printf("[%d:%s] = %lf\n", s.id, s.pname, s.points);}

void print_student2(STUD *ps){

printf("[%d:%s] = %lf\n", ps->id, ps->pname, ps->points);}

int main(void){

STUD pnuecs[2] = { {1, "Choi", 9.9}, {2, "Park", 0.1} };

print_student(pnuecs[0]);print_student2(&pnuecs[1]);

return 0;}