Skip to content

Instantly share code, notes, and snippets.

@tiger1710
Last active February 11, 2020 00:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tiger1710/0340f29339f9c660e655dbe957e80e85 to your computer and use it in GitHub Desktop.
Save tiger1710/0340f29339f9c660e655dbe957e80e85 to your computer and use it in GitHub Desktop.

C에서의 구조체

들어가면서

코딩 꼭 같이 해보면서 해보세요.. ㅠㅠ 그럼 더 이해 잘 될것 같네요..

1. 배경

만약 학생을 데이터로 표현하고 싶다고하면, 이름, 학번, 학년을 데이터로 저장해야 한다.

이때 char name[] = "홍길동"; int id = 1871000; int grade = 1; 이런식으로 3개씩 선언하여 사용해야한다.

하지만 학생을 100명 표현해야한다면?? --> 많이 힘들다... ㅠㅠ

그래서! 구조체가 나왔당

struct student {//구조체의 이름이 student인 구조체 선언
    char name[30];//char[30] 이름 배열
    int id;//학번
    int grade;//학년
};

로 구조체를 만들 수 있다.

main에서 사용할때는 struct student person; 으로 선언할 수 있다.

여기서 struct student 가 자료형이고, person이 변수명이예요 주의.

2. 사용법

구조체를 정의하고 만들었다면, 사용도 해야겠죠!

#include <stdio.h>

struct student {//구조체의 이름이 student인 구조체 선언
    char name[30];//char[30] 이름 배열
    int id;//학번
    int grade;//학년
};

int main(void) {
    struct student person = { "홍길동", 1871000, 1 };
    printf("%s\n", person.name);
    printf("%d\n", person.id);
    printf("%d\n", person.grade);
    
    scanf("%s", person.name);
    scanf("%d", &person.id);
    scanf("%d", &person.grade);
    
    return 0;
}

main함수에서 구조체를 선언한 후에, 값을 바로 할당하는 것을 해봤습니다. 선언하고 바로 할당하고 싶다면 중괄호로 구조체안의 내용물을 채워준다고 생각하면 될 거 같아요.

그래서 "홍길동"은 name에, 1871000은 id에, 1은 grade에 각각 맵핑됩니다. 그리고 11~13까지는 출력하는 부분입니다. 구조체변수에 접근하고 싶다면 구조체변수의이름.변수명 으로 접근할 수 있어요. 여기서는 person이 구조체의 변수명이니까, person.name, person.id, person.grade 로 접근하는 것이죠.

그리고 입력을 하고싶다! 하면 똑같이 scanf를 사용해서 구조체의 어디에 입력할 것인지 정하면됩니다. scanf("%s", person); 이런건 절대 안됩니다! 구조체에 직접 입력을 할 순 없습니다. 구조체의 어떤변수 에 입력할 것인지 확실하게 정해주어야 합니다.

여기서 scanf("%s", person.name); 은 왜 &가 없냐? -> 배열의 이름은? 배열의 시작주소! 가 여기서도 적용됩니다. 따라서 %s로 문자열을 입력받을 때, person.name은 구조체 안에있는 name배열의 시작주소이지요? 그래서 &가 안붙습니다. 다른변수들은 일반 변수사용시와 같이 &를 꼭! 붙여주어야 합니다.

3. 구조체 배열

저희가 int arr[10]; 이렇게 자료형에 대한 배열을 만들었었죠. 구조체또한 가능합니다. 구조체도 엄연히 사용자 정의__자료형__ 이기 때문이죠.

struct student person[10]; 으로 선언할 수 있습니다. 여기서부터는 제가 구조체좀 쉽게 쓰려고 합니다.

typedef struct student {
    char name[30];
    int id;
    int grade;
}Student;

이렇게 하게되면 struct person 을 Person으로 맵핑해서 사용하겠다는 겁니다. 즉, typedef A B는 A를 B로 사용하겠다는 것이죠. 사용 할때에는 Student a; 로하면 struct student a; 와 같은 효과입니다.

typedef int data;

data i = 10; 이렇게 하게되면 data는 int 인 것입니다. 따라서 위의 typedef 문은 Student을 사용할 때 struct student을 사용하겠다는 것입니다.

typedef 를 적용하면,

Student person[10]; 이렇게 구조체배열 을 선언할 수 있죠. 전에 저희가 int 형 배열을 선언해서 [0], [1] 이렇게 접근한 것 처럼 구조체배열도 똑같이 접근할 수 있습니다. arr[0] 이렇게하면 구조체배열의 첫번째 값에 접근한겁니다. 그렇다면 person[0].name 은 첫 번째 구조체의 name 변수가 되는거죠. 마찬가지로 person[0].id, person[0].grade 에 값을 쓰거나 읽을 수 있습니다. 배열이나오면 항상따라오는것이 반복문이죠 ㅎㅎ

#include <stdio.h>

typedef struct student {
    char name[30];
    int id;
    int grade;
}Student;

int main(void) {
    Student arr[10];//구조체 배열 선언
    for (int i = 0; i < 10; i++) {//데이터 입력부분
        scanf("%s %d %d", arr[i].name, &arr[i].id, &arr[i].grade);
    }
    
    for (int i = 0; i < 10; i++) {//데이터 출력부분
        printf("%s %d %d", arr[i].name, arr[i].id, arr[i].grade);
    }
    
    return 0;
}

이처럼 구조체배열을 잘 이용하실 수 있어야합니다..

4. 구조체 포인터

전에 했던 코드를 살펴볼까여

int a = 10;
int* p = &a;

이렇게 하면 p를 이용해서 a값을 변경하거나 출력할 수 있죠.

(*p)로 a의 값을 바꾸거나 얻을 수 있죠.


구조체의 포인터도 마찬가지입니다!

typedef struct student {
    char name[30];
    int id;
    int grade;
}Student;

Student person = { "홍길동", 1871000, 1 };
Student* p = &person;

같은 방식입니다. Student 구조체 자료형인 person을 선언하고 값을 할당한 후에, Student 구조체자료형의 포인터 인 p를 선언하고 p는 person을 가리킵니다. 여기까진 같습니다.

하지만 멤버 접근시에 달라지는데요, 위에서 값에 접근할 때 *을 사용한다고 했습니다. 그렇다면 구조체에서 똑같이 적용할 수 있습니다. (*p).name , (*p).id , (*p).grade 로 접근하실 수 있습니다. 여기서 (*person) 을 괄호로 감싸준 이유는 . 연산자가 * 연산자보다 더 우선순위가 높기 때문입니다. 그래서 불편하죠?... ㅠㅠ 맨날 감싸줘야 되서요..

그래서 ->가 나왔습니다! 구조체 포인터한정으로 구조체 포인터가 있을 때 -> 연산자를 이용해서 구조체의 멤버에 접근할 수 있도록 했습니다.

#include <stdio.h>

typedef struct student {
	char name[30];
	int id;
	int grade;
}Student;
int main(void) {
    Student person;
    Student* p = &person;

    scanf("%s", p->name);
    //scanf("%d", (*p).name);와 동일(왜 &안붙는지는 아시죠?)
    scanf("%d", &p->id);
    //scanf("%d", &(*p).id);와 동일
    scanf("%d", &p->grade);
    //scanf("%d", &(*p).grade);와 동일


    printf("%s\n", p->name);//(*p).name
    printf("%d\n", p->id);//(*p).id
    printf("%d\n", p ->grade);//(*p).grade;

	return 0;
}

이런식으로 말이죠.. 괄호로 감싸주고.. 별찍고 변수명 할 필요없이 ->면 바로 접근할 수 있어서 좋은겁니다!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment