C언어: 구조체 (Structure)
예시) 학생 데이터
학생의 정보 = 학번, 이름, 학점 등을 포함
-> 구조체를 통해 ‘한 학생’ 단위로 묶을 수 있다.
struct student
{
int id;
char* name;
float gpa;
}; // 세미콜론 주의
-> struct student
라는 타입 새로 생성
student
: 구조체의 tag에 해당한다.
struct student s; // 새 '학생' 변수 선언
or struct student s[100]; // 배열로 선언도 가능하다.
typedef
를 통해 짧게 할 수도 있다. typedef struct student {} Student;
등
타입을 정의 않고 바로 구조체 변수를 생성도 가능하다.
struct
{
int id;
char* name;
float gpa;
} student1, student2;
//struct {} <- 타입, student1, student2 <-변수명
구조체 멤버 접근
s.id = 2021320133;
s.name = "정준모";
와 같이 접근한다.
구조체 초기화
struct student s = {10,Chung,4.5};
와 같이 가능
구조체 argument
구조체를 함수의 argument로 대입할 경우, 구조체의 복사본이 전달된다.
구조체 return
구조체 복사본이 return 된다. (대입 가능)
구조체 assignment
구조체 복사본이 assign 된다.
-> 놀랍게도 구조체 내의 배열까지 복사된다.
이 특성을 이용하기 위해 배열 복사를 위한 dummy 구조체를 만들기도 한다.
주의사항) 구조체는 대부분의 연산자가 사용 불가하다. 예를 들어, == 나 != 사용 불가하다.
Designated Initializers
배열과 비슷하게 사용 가능
struct {
int no;
char name[N+1];
} student1 = {.no=1};
과 같이 사용 가능하다. (점 반드시 찍어야 함에 주의)
장점: 순서 기억하지 않아도 되고 더 명확하다.
구조체 포인터와 Linked List (연결 리스트)
typedef struct node
{
int val;
struct node* next;
} Node, *NodePtr;
쉼표 이후 : typedef struct node* NodePtr
로 해석 된다. (태그 생략해도 상관 없다).
연결 리스트를 사용할 때에는 태그 사용이 mandatory하다고 한다.
-
이유: 자기 자신을 가리키는 포인터 멤버를 선언하기 위해서는 태그가 존재해야만 가능하다.
-
typedef과 같이 사용해도 상관은 없는 것 같다.
NodePtr head; // 첫 번째 노드를 가리킨다
NodePtr current; // 현재 노드를 가리킨다
마지막 노드의 next
는 NULL
가리킨다
*(head).val;
-> head
가 가리키는 노드의 val
변수에 접근
head -> val;
도 같은 효과를 내는 statement 이다!
연결 리스트의 사용 목적
연속적인 공간을 할당하지 않고도 여러 노드가 배열과 같이 선형적으로 연결되는 효과를 내기 위함.
Tips
- 연결리스트는 왼쪽으로 자라게 하면 코드를 간결하게 작성할 수 있다.
구조체의 Compound Literals
구조체도 compound literal 형태로 함수에 전달 가능하다.
ex) (struct part) {1, "name", 2}
-> 이미 선언된 구조체 변수에 할당하는 용도로도 사용 가능
Pointers to compound linterals
&
붙이면 포인터 전달도 가능
-> 이 경우, 역참조를 통해 modify도 가능하다 (compound literal은 lvalue에 해당한다.)