티스토리 뷰
Chapter 13.
구조체란?
다양한 기본 자료형을 가진 요소들을 모아 새로운 자료형으로 만든 것이다.
구조체와 배열의 공통점은 여러 개가 모여 새로운 하나가 되었다는 점이다.
그러나 배열은 '같은 것'이 여러 개 모여 한 덩어리를 이룬 것이고, 구조체는 서로 다른(같을 수도 있음) 것들이 여러 개 모여 저혀 새로운 한덩어리를 이룬 것이라는 점에서 다르다.
배열은 배열을 이루고 있는 각각을 요소라고 부르고, 구조체는 멤버라고 부른다.
13.1 구조체
구조체가 식판이면 식판의 한 요소를 담당하는 그릇 하나하나는 그 식판의 멤버라고 생각하면 된다.
구조체나 공용체 같은 것을 사용자 정의 자료형이라고 한다.
13.1.1 구조체 선언 및 정의
#include<stdio.h>
#include<string.h>
//구조체 선언
struct USEDATA{
int nAge;
char szName[32];
char szPhone[32];
};
int main(void){
//USEDATA 구조체 변수 user 선언 및 정의
struct USEDATA user = {0, "", ""};
//구조체 멤버 접근 및 값 채우기
user.nAge = 10;
strcpy(user.szName, "Nemo");
strcpy(user.szPhone, "010-1234-1234");
//구조체 멤버 접근 및 출력
printf("%d살, %s, %s\n", user.nAge, user.szName, user.szPhone);
return 0;
}
※구조체를 이루고 있는 멤버들의 순서에 맞춰서 초깃값을 기술해야 한다는 점에 주의해야 한다.
18행의 경우 구조체 멤버 접근연산의 결과가 간접지정처럼 l-value가 될 수 있지만, 19/20행의 경우 구조체의 멤버가 배열이면 l-value가 될 수 없습니다.
typedef를 이용한 형 재선언
#include<stdio.h>
#include<string.h>
//구조체 선언 및 형 재선언
typedef struct USERDATA{
int nAge;
char szName[32];
char szPhone[32];
} USERDATA;
int main(void){
//형 재선언 덕분에 변수를 선언할 때 'struct'를 생략할 수 있다.
USERDATA user = {0, "", ""};
//구조체 멤버 접근 및 값 채우기
user.nAge = 10;
strcpy(user.szName, "Nemo");
strcpy(user.szPhone, "010-1234-1234");
//USERDATA 구조체 배열 선언 및 정의
USERDATA userList[4] = {
{10, "김어준", "1234"},
{11, "아무개", "2345"},
{16, "김나은", "3456"},
{18, "백지헌", "4567"}
};
//구조체 멤버 접근 및 출력
printf("%d살, %s, %s\n", user.nAge, user.szName, user.szPhone);
for(int i =0; i < 4; i++)
printf("%d살 \t%s\t%s\n", userList[i].nAge, userList[i].szName, userList[i].szPhone);
return 0;
}
13.1.2 구조체 동적 할당
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct USERDATA{
int nAge;
char szName[32];
char szPhone[32];
} USERDATA;
int main(void){
//USERDATA 구조체에 대한 포인터 변수 선언 및 정의
USERDATA *pUser = NULL;
//USERDATA 구조체가 저장될 수 있을 수 있는 크기의 메모리 동적 할당
pUser = (USERDATA*)malloc(sizeof(USERDATA));
//포인터 이므로 '.'이 아니라 '->'연산자로 멤버에 접근한다!
pUser->nAge = 10;
strcpy(pUser->szName, "Hoon");
strcpy(pUser->szPhone, "9876");
printf("%d살 \t%s\t%s\n", pUser->nAge, pUser->szName, pUser->szPhone);
return 0;
}
pUser->nAge == (*pUser).nAge
하지만, *pUser.nAge라고 표기하면 간접지정 연산자보다 구조체 멤버 접근 연산자가 우선하므로, 결과적으로 'char형 l-value'가 된다.
13.1.3 반환자료, 매개변수 구조체
구조체도 함수의 반환 자료형이나 매개변수가 될 수 있다. 그리고 구조체 변수는 배열의 이름(주소상수)과 달리 l-value가 될 수 있다.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct USERDATA{
int nAge;
char szName[32];
char szPhone[32];
} USERDATA;
//구조체 인스턴스가 아니라
//구조체에 대한 '포인터'를 매개변수로 받는다. 따라서 효율적이다.
void GetUserData(USERDATA *pUser){
scanf("%d%*c", &pUser->nAge);
gets_s(pUser->szName, sizeof(pUser->szName));
gets_s(pUser->szPhone, sizeof(pUser->szPhone));
}
int main(void){
USERDATA user = {0};
//Call by reference로 변경
GetUserData(&user);
printf("%d살 \t%s\t%s\n", user.nAge, user.szName, user.szPhone);
return 0;
}
자기 참조 구조체
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct USERDATA{
char szName[32];
char szPhone[32];
//USERDATA 구조체를 가리킬 수 있는 포인터를 멤버로 선언!
struct USERDATA *pNext;
} USERDATA;
int main(void){
//두 개의 USERDATA 구조체 인스턴스 선언 및 정의
USERDATA user = {"김어준", "1234", NULL};
USERDATA newUser = {"정봉주", "2345", NULL};
//pNext 멤버를 이용해 두 인스턴스를 연결한다.
user.pNext = &newUser;
printf("%s\t%s\n", user.szName, user.szPhone);
//pNext 멤버를 이용해 구조상 다음 인스턴스에 접근한다.
printf("%s\t%s\n", user.pNext->szName, user.pNext->szPhone);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct USERDATA{
char szName[32];
char szPhone[32];
//USERDATA 구조체를 가리킬 수 있는 포인터를 멤버로 선언!
struct USERDATA *pNext;
} USERDATA;
int main(void){
//배열로 USERDATA 구조체 인스턴스 넷을 선언 및 정의
USERDATA userList[4] = {
{"김어준", "1234", NULL},
{"고기는", "2345", NULL},
{"살리는", "3456", NULL},
{"인턴은", "4567", NULL}
};
//연결 리스트의 첫 번째 인스턴스의 주소를 저장할 포인터
USERDATA *pUser = NULL;
//pNext 멤버를 배열의 순서상 다음 구조체 인스턴스의 주소로 정의한다.
userList[0].pNext = &userList[1];
userList[1].pNext = &userList[2];
userList[2].pNext = &userList[3];
//마지막 인스턴스는 뒤에 아무것도 없으므로 NULL로 초기화 한다.
userList[3].pNext = NULL;
//연결된 리스트의 첫 번째 인스턴스를 가리키도록 포인터를 정의한다.
pUser = &userList[0];
while (pUser != NULL){
//포인터가 가리키는 인스턴스의 멤버를 출력한다.
printf("%s, %s\n", pUser->szName, pUser->szPhone);
//현재 가리키고 있는 인스턴스의 다음 인스턴스를 가리키도록
//포인터를 다음으로 '이동' 시킨다!
pUser = pUser->pNext;
}
return 0;
}
13.1.5 구조체 멤버 맞춤
#pragma pack 전처리기를 이용하면 특정 구조체만 멤버를 1바이트로 맞출 수 있습니다.
#pragma pack(push, 1)
...
#pragma pack(pop)
'언어 > C' 카테고리의 다른 글
파일 시스템 기본 이론 - 독하게 시작하는 C프로그래밍 (0) | 2019.10.23 |
---|---|
비트필드, 공용체 - 독하게 시작하는 C프로그래밍 (0) | 2019.10.04 |
Call by value, Call by reference - 독하게 시작하는 C프로그래밍 (0) | 2019.10.03 |
포인터의 배열과 다중 포인터 - 독하게 시작하는 C프로그래밍 (0) | 2019.09.21 |
메모리 동적 할당 및 관리 - 독하게 시작하는 C프로그래밍 (0) | 2019.09.19 |
- Total
- Today
- Yesterday
- 강의
- 공부
- timecomplexity
- 2차원 배열
- 알고리즘
- codeit
- 종류
- C
- call by reference
- 간접 지정
- 1차원 배열
- 자료구조
- 파이썬
- 포인터
- 회전리스트
- 구조체
- 프로그래밍
- 시간복잡도
- 형승격
- 배열
- 직접 지정
- 공간복잡도
- 3차원 배열
- Algorithm
- 공용체
- inflearn
- 재귀함수
- 비트필드
- call by value
- 다차원 배열
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |