🖥️ CS, 개발상식/자료구조

[자료구조/C] 구조체

dev_zoe 2020. 7. 26. 19:49
반응형

구조체란?

  • 타입이 다른 데이터를 묶는 방법

구조체 정의 - 구조체 명

struct student {
    int id;
    char name[20];
    int midterm;
    int final;
};

 

student : 구조체와 구조체를 구별해주는 식별자. 구조체 태그 라고도 함

id, miterm, name, final : 구조체 멤버

 

  • 구조체 변수 선언 : struct student aStudent; -> 이렇게 선언해야만 메모리가 잡힘
  • 구조체 변수 선언과 초기화 동시에 : struct student aStudent = {20191111, "율짱", 100, 90};

구조체 정의 - 구조체 타입

typedef struct student{
    int id;
    char name[20];
    int midterm;
    int final;
} Student;

 

student : 구조체 태그(구조체 명) -> 구조체 타입 정의 방법에서 생략 가능

Student : 구조체 타입

 

  • 구조체 변수 선언 : Student aStudent;

구조체 멤버 변수 사용

'.'(dot, 멤버 연산자(membership operator)을 사용한다.

 

ex 1 aStudent의 각각의 멤버 변수의 값을 입력받는다

 

scanf("%d", aStudent.id);

scanf("%s", aStudent.name);

scanf("%d", aStudent.midterm);

scanf("%d", aStudent.final);

 

구조체 배열

struct student sList[3]; -> sList[0], sList[1], sList[2]는 각각 구조체 변수

 

ex 1 구조체 배열의 원소들의 각 멤버 값을 입력받음

 

for (i=0; i<3; i++){
    printf("학번, 이름, 중간, 학기말 입력: ");
    scanf("%d %s %d %d", &sList[i].id, &sList[i].name, &sList[i].midterm, &sList[i].final);
}

 

구조체 포인터

  • 구조체 포인터 선언 : struct student *sp = &aStudent;
  • 구조체 변수 접근 : -> 연산자 사용

ex 1 포인터 sp를 사용하여 구조체 멤버 각각에 값 설정

 

sp->id = 20151952;

strcpy(sp->name, "율짱");

sp->midterm = 100;

sp->final = 90;

 

ex 2 포인터 sp를 사용하여 구조체 멤버의 값을 입력받음

 

scanf("%d", &sp->id);

scanf("%s", &sp->name);

scanf("%d", &sp->midterm);

scanf("%d", &sp->final);

 

  • sp->id는 (*sp).id와 같다. 여기서 *보다 . 이 우선순위가 높기때문에, 먼저 *sp로 구조체를 가리키고 그의 id를 접근해야한다.

구조체 배열과 구조체 포인터

struct student sList[3];

 

struct student *sp = sList;

 

//배열의 이름 = 배열의 첫 번째 요소의 주소값이므로, (sList = &sList[0])

sp는 sList 배열의 첫 번째 요소(sList[0])를 가리킨다.

 

sp가 다음 원소를 가리키게 하려면? -> sp++;

 

구조체를 함수 매개변수로 전달

#include <stdio.h>

typedef struct{
    char name[10];
    int age;
} Person;

void printPerson1(Person p) //값에 의한 호출(call-by-value)
{
	printf("%s %d", p.name, p.age);
}

void printPerson2(Person *p) //참조에 의한 호출(call-by-reference)
{
	printf("%s %d", p->name, p->age);
}

int main(void){
    Person aPerson = {"yulzzang", 25};
    
    printPerson1(aPerson);
    printPerson2(&aPerson);
}

 

  • 값에 의한 호출(call-by-value) : 구조체를 매개 변수로 전달하는데 이 때 구조체의 값을 복사함
  • 참조에 의한 호출(call-by-reference) : 구조체의 주소를 매개 변수로 전달함

 

#include <stdio.h>

void tenYearsAfter1(Person p)
{
	p.age+=10;
}

void tenYearsAfter2(Person *p)
{
	p->age += 10; //or (*p).age+=10;
}

int main(void){
    Person aPerson = {"yulzzang", 25};
    
    tenYearsAfter1(aPerson);
    tenYearsAfter2(&aPerson);
}

 

tenYearsAfter1에서 aPerson의 age는 그대로 30이고, tenYearsAfter2에서 aPerson의 age는 40이다.

그 이유는 tenYearsAfter1는 call-by-value인데, 이 경우 구조체 p가 값을 복사해서 10을 더하기 때문에 aPerson의 값은 바뀌지 않게된다.

반면에 tenYearsAfter2는 call-by-reference인데, 이 경우 aPerson의 주소값을 매개변수로 전달하면 포인터 p가 aPerson을 가리키기 때문에 aPerson의 값이 변경된다.

 

따라서, 함수 안에서 인수로 전달되는 구조체의 내용이 바뀌어야하면 반드시 call-by-reference로 매개변수를 전달해야한다.

 

 

반응형