1. 구조체 변수로 가능한것과 불가능한 것
구조체 변수의 활용방법은 일반변수와 크게 차이가 없다. 변수로 가능한 대부분의 일이 가능하다.
1) 함수의 인자로 전달도 가능하다.
2) 반환도 가능하다.
3) 대입 연산의 피연산자로도 사용이 가능하다.
4) 단 사칙연산은 불가능하다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include <stdio.h> struct __point { double xPos; double yPos; }; typedef struct __point point; point IncrePos(point pnt) { pnt.xPos++; pnt.yPos++; return pnt; } int main(void) { point p1, p2, p3; p1.xPos=0.5; p1.yPos=1.5; p2=p1; p3=IncrePos(p2); printf("X: %g \n", p3.xPos); printf("Y: %g \n", p3.yPos); return 0; } | cs |
1 2 | X: 1.5 Y: 2.5 | cs |
• 10행 : point가 자료형의 이름이기 때문에 이를 반환형과 매개변수형으로 선언할 수 있다. 즉 함수 IncrePos는 point형 데이터를 인자로 받고, point형 데이터를 반환하는 함수이다.
• 23행 : 일반 변수와 동일하게 대입연산이 가능하다. 이 대입연산으로 인해서 p1의 모든 값은 p2에 복사된다.
• 24행 : IncrePos 함수를 호출하면서 p2를 인자로 전달하고 있다. 따라서 p2에 저장된 값이 전달되어 매개변수가 초기화 된다. 그리고 반환 값은 p3에 저장이 된다.
참고로 위 예제 24행에서 이뤄지는 값의 복사 과정을 그림으로 정리하면 다음과 같다.
그리고 구조체 변수를 이용한 사칙연산도 위 예제를 보면 가능할 것도 같아 보인다. point 구조체를
형성하는 두 개의 구조체 멤버가 실수이기 때문이다. 그러나 구조체 변수를 이용한 사칙연산은 허용
되지 않는다. 구조체 멤버에는 문자열의 저장이 가능한 char형 배열처럼 사칙연산을 적용하기 어려
운 대상도 포함될 수 있기 때문이다.
그리고 구조체 변수는 복합대입 연산자 += 의 피연산자가 될수 없다. 왜냐하면 연산자 += 의 경우
대입연산 이전에 덧셈연산을 거쳐야 하기 때문이다.
2. 배열을 멤버로 하는 구조체의 정의와 대입연산
구조체의 멤버에는 배열도 올 수 있다. 그리고 이렇게 멤버로 배열이 오게 될 경우,대입연산을
통해서 배열을 통째로 복사하는 것이 가능하다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #include <stdio.h> #include <string.h> #define NAME_LEN 30 #define PID_LEN 15 struct __person { char name[NAME_LEN]; // 이름 char ID[PID_LEN]; // 주민등록 번호 unsigned int age; // 나이 }; typedef struct __person person; void ShowPersonData(person prsn) { printf("이름: %s \n", prsn.name); printf("주민등록 번호: %s \n", prsn.ID); printf("나이: %u \n", prsn.age); } int main(void) { person jongsoo; person copyman; strcpy(jongsoo.name, "한종수"); strcpy(jongsoo.ID, "900218-1012589"); jongsoo.age=20; copyman=jongsoo; ShowPersonData(copyman); return 0; } | cs |
1 2 3 | 이름: 한종수 주민등록 번호: 900218-1012589 나이: 20 | cs |
• 8, 9행 : 구조체의 멤버로 배열이 선언되었다. 이처럼 구조체 안에는 배열이 선언될 수 있다.
• 14행 : 이 함수는 구조체 person의 데이터를 인자로 전달받아서, 그 안에 저장되어 있는 데이터를 출력하도록 정의되었다.
• 26, 27행 : 23행에서 선언한 구조체 변수의 멤버 일부를 초기화하고 있다. 문자열을 복사 저장해야 하기 때문에 strcpy 함수의 도움을 받아야 한다.
• 30행 : 구조체 변수 jongsoo에 저장된 값을 동일한 자료형의 변수인 copyman에 대입연산을 통해서
복사하고 있다. 이 경우에 jongsoo에 저장된 모든 멤버의 데이터가 copyman에 그대로 복사 된다.
• 31행 : 30행의 대입연산으로 초기화 된 변수 값의 출력을 위해 ShowPersonData 함수를 호출하고 있다.
지금까지는 대입연산을 통한 배열의 복사가 불가능했다. 뿐만 아니라 함수의 전달인자로 배열의 주소
값만 전달이 가능했을 뿐,배열 자체를 전달하는 것도 불가능했다. 그러나 위 예제에서는 대입연산을
통해서 배열을 복사도 하고,함수의 매개 변수로 배열 자체를 전달도 하고 있다. 비록 구조체의 멤버
로 선언된 배열이긴 하지만 말이다.
다음 그림은 위 예제의 30행과 31행에서 일어나는 상황을 정리해 놓은 것이다.
- 대입연산과 인자전달 과정에서의 구조체 멤버의 복사방식
3. 구조체와 구조체 포인터
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <stdio.h> #include <string.h> #define NAME_LEN 30 #define PID_LEN 15 struct __person { char name[NAME_LEN]; // 이름 char ID[PID_LEN]; // 주민등록 번호 unsigned int age; // 나이 }; typedef struct __person person; void ShowPersonData(person * ptr) { printf("이름: %s \n", (*ptr).name); printf("주민등록 번호: %s \n", (*ptr).ID); printf("나이: %u \n", ptr->age); } int main(void) { person jongsoo; person copyman; person * personPtr; strcpy(jongsoo.name, "한종수"); strcpy(jongsoo.ID, "900218-1012589"); jongsoo.age=20; copyman=jongsoo; personPtr=©man; ShowPersonData(personPtr); return 0; } | cs |
1 2 3 | 이름: 한종수 주민등록 번호: 900218-1012589 나이: 20 | cs |
• 14행 : 구조체 person의 주소값을 인자로 전달받도록 함수가 변경되었는데, 여기서 사용된 매
개변수의 포인터 선언 방식은 기본 자료형 변수의 포인터 선언방식과 동일하다.
• 25행 : 구조체 변수의 포인터 선언방식을 보여준다.
• 32행 : 구조체 변수의 주소 값을 얻을 때도 & 연산자를 사용한다.
• 16~18행 : 포인터를 이용한 구조체 변수의 접근과 관련된 내용으로, 34행의 함수 호출문장이
실행되면, 14행에 선언된 매개변수 ptr은 24행에 선언된 구조체 변수 copyman을 가리키게 된
다. 따라서 (*ptr)은 구조체 변수 copyman을 의미하게 되어, copyman의 멤버에 접근하기 위해서
는 다음과 같이 연산문을 구성해야 한다.
• ptr이 가리키는 구조체 변수의 name 접근 : (*ptr).name
• ptr이 가리키는 구조체 변수의 ID 접근 : (*ptr).ID
• ptr이 가리키는 구조체 변수의 age 접근 : (*ptr).age
멤버에 접근하는 위 문장에서 괄호가 필요한 이유는 . 연산자보다 * 연산자의 우선순위가 낮기 때
문이다. 그리고 C언어에서는 위와 같이 포인터를 이용한 구조체 멤버의 접근을 간단히 처리할
수 있도록 -> 연산자를 제공하고 있다. 이 연산자를 사용하면 다음과 같은 방식으로 접근이 가능
하다.
• ptr이 가리키는 구조체 변수의 name 접근 : ptr->name
• ptr이 가리키는 구조체 변수의 ID 접근 : ptr->ID
• ptr이 가리키는 구조체 변수의 age 접근 : ptr->age
즉 (*pointer).member는 pointer->member와 완전히 동일한 연산문이다.
그러나 후자의 방식이 보다 간결한 형식을 띠기 때문에 일반적으로 많이 사용된다.
4. 구조체 변수의 선언과 초기화
구조체 변수의 초기화 방법은 마치 배열의 초기화와 유사하다. 즉 초기화할 값을 중괄호 안에 쉼
표로 구분 지어 표시하면 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #include <stdio.h> #define NAME_LEN 30 #define PID_LEN 15 struct __person { char name[NAME_LEN]; // 이름 char ID[PID_LEN]; // 주민등록 번호 unsigned int age; // 나이 }; typedef struct __person person; void ShowPersonData(person * ptr) { printf("이름: %s \n", (*ptr).name); printf("주민등록 번호: %s \n", (*ptr).ID); printf("나이: %u \n\n", ptr->age); } int main(void) { person jongsoo={"한종수", "900218-1012589", 20}; person sungeun={"이성은", "910218-1012589", 19}; ShowPersonData(&jongsoo); ShowPersonData(&sungeun); return 0; } | cs |
1 2 3 4 5 6 7 | 이름: 한종수 주민등록 번호: 900218-1012589 나이: 20 이름: 이성은 주민등록 번호: 910218-1012589 나이: 19 | cs |
• 22, 23행 : 구조체 변수를 선언과 동시에 초기화하고 있다. 중괄호 안에다가 구조체의 멤버가 선언된 순서대로, 초기화할 값을 정리해서 삽입하고 있다.
'BackEnd > C' 카테고리의 다른 글
구조체 배열 (0) | 2019.03.23 |
---|---|
구조체의 정의에 포함되는 typedef 선언 (0) | 2019.03.23 |
구조체의 정의 (0) | 2019.03.22 |
구조체의 필요성 (0) | 2019.03.21 |
대표적인 선행처리 명령문 (0) | 2019.03.21 |