강의

멘토링

커뮤니티

인프런 커뮤니티 질문&답변

maritime23님의 프로필 이미지
maritime23

작성한 질문수

(2026) 일주일만에 합격하는 정보처리기사 실기

구조체

아 진짜 구조체 이해 안되는데요

해결된 질문

작성

·

24

0

아니 구조체 포인터는 뭐고 구조체 포인터 사용하여 함수호출은 뭐고.. 하.. 너무 쉽게쉽게 넘어가시는거같아요 저는 빡대가리인데.

답변 3

0

maritime23님의 프로필 이미지
maritime23
질문자

AI보다 정확하고 쉬운 설명 감사합니다. 이해가 너무 잘되었습니다.

주말코딩님의 프로필 이미지
주말코딩
지식공유자

앞으로도 계속 어려울 수 있습니다.

많은 질문 부탁드립니다.

0

주말코딩님의 프로필 이미지
주말코딩
지식공유자

안녕하세요, 많이 어려우시죠.

아예 코드를 처음 배우시는 분들이라면 C언어 자체가 어려울 수 있습니다.

컴퓨터공학과 1학년 때 C언어를 6개월 간 배웠던 저도 그랬고요.

옆에서 붙어서 과외처럼 가르쳐주지 않는 한, 원래 어려운 것이 맞습니다.

 

우선 문법은 둘째치고,

개념 자체가 어려우신 것 같습니다.

첫번째는 포인터 개념이고 두번째는 "함수를 호출한다"라는 개념입니다.

8:14에 나온 코드 기준으로 좀 더 구체적으로 설명해볼게요.

#include <stdio.h>

#include <string.h>

// 구조체 정의

struct Bag {

  char brand[50]; // 브랜드명을 저장할 문자열 배열
  int year; // 제작 연도를 저장할 정수형 변수
  float price; // 가격을 저장할 실수형 변수

};

// 구조체 포인터를 인수로 받아서 출력하는 함수 정의

void printBag(struct Bag * bag) {
  printf("Brand: %s\n", bag -> brand);
  printf("Year: %d\n", bag -> year);
  printf("Price: %.2f\n", bag -> price);
}

int main() {

  struct Bag myBag; // 구조체 변수 선언
  struct Bag * bagPtr = & myBag;
  // 구조체 포인터 선언 및 초기화

  // 포인터를 통해 값 할당
  strcpy(bagPtr -> brand, "Gucci");
  bagPtr -> year = 2021;
  bagPtr -> price = 1500.50;
  printBag(bagPtr);

  // 구조체 포인터를 사용하여 함수 호출
  return 0;

}
주말코딩님의 프로필 이미지
주말코딩
지식공유자

포인터 — 상자의 "주소"를 적어둔 메모지

포인터가 어려운 이유는, 값 자체가 아니라 "값이 있는 위치(주소)" 를 다루기 때문입니다.

비유해볼게요.

친구가 "내 가방 어디있어?" 라고 물었을 때,

가방을 직접 들고 와서 주는 것 → 변수 (값 자체) "거실 테이블 위에 있어"라고 위치를 알려주는 것포인터 (주소)

코드로 보면:

int year = 2021;        // 상자에 값을 넣음
int *ptr = &year;       // ptr이라는 메모지에 year의 주소를 적어둠

여기서 기호 두 개만 기억하세요.

&year -> year의 주소를 가르쳐달라는 뜻
*ptr -> ptr이 가리키는 곳의 값을 꺼내라는 뜻

정리: 포인터는 그냥 "다른 변수의 주소를 저장하는 변수"입니다. 그게 전부예요.

주말코딩님의 프로필 이미지
주말코딩
지식공유자

구조체 — 여러 상자를 하나로 묶은 가방

변수 하나에는 값 하나만 넣을 수 있잖아요?

그런데 현실에서는 하나의 물건에 여러 정보가 있죠.

 

예를 들어 가방 하나에 대해:

  • 브랜드명 (글자)

  • 제작연도 (숫자)

  • 가격 (소수점 숫자)

이걸 따로따로 만들면 너무 번거롭습니다.

(이게 Java로 가면 Class라는 개념으로 확장됩니다. 여러 데이터를 하나로 묶는다는 점에서 둘 다 비슷한 개념입니다.)

// 이렇게 하면 변수가 너무 많아져요...

char brand[50] = "Gucci";
int year = 2021;
float price = 1500.50;

그래서 하나로 묶은 게 구조체인 것입니다.

struct Bag {
    char brand[50];   // 브랜드명
    int year;         // 제작연도
    float price;      // 가격
};

 

이렇게 하면 앞으로 저 Bag라는 것 자체를 단위로 쓸 수 있습니다.

근데 아직 우리는 Bag라는 개념만 정립한 것이고 실제 변수로 쓰려면 앞에 struct라는 키워드를 붙여서 main 함수에서 써야합니다.

 

struct Bag myBag;   // 설계도(Bag)를 바탕으로 실제 가방(myBag)을 하나 만듦

그림으로 보면:
myBag (구조체 변수 = 큰 상자)
┌─────────────────────────────┐
│  brand: "아직 비어있음"      │
│  year:  아직 비어있음        │
│  price: 아직 비어있음        │
└─────────────────────────────┘

 

저 변수에다가 변수를 넣은 것이 아래처럼 한 것입니다.

strcpy(myBag.brand, "Gucci");  // 문자열은 strcpy로 복사
myBag.year = 2021;
myBag.price = 1500.50;
주말코딩님의 프로필 이미지
주말코딩
지식공유자

자, 이제 maritime님이 질문하신 구조체 포인터를 설명하겠습니다.

앞에서 배운 포인터를 그냥 구조체에 적용한 거에요. 그렇게 받아들이시면 됩니다. 더 어려운 것 없습니다. 진짜 그게 끝입니다.

struct Bag myBag;              // 실제 가방
struct Bag *bagPtr = &myBag;   // 가방의 주소를 적어둔 메모지
```

그림:
```
bagPtr (메모지)              myBag (실제 가방)
┌──────────┐                ┌─────────────────────┐
│ 0x2000   │ ─────────────→ │  brand: ""          │
└──────────┘                │  year:  0           │
 "myBag의 주소를             │  price: 0.0         │
  들고 있음"                 └─────────────────────┘

 

여기서의 차이가 있다면,

구조체를 직접 쓸 때는 .(점)으로 접근하고 포인터로 접근할 때는 -> 화살표를 씁니다.

// 직접 접근 (점 사용)
myBag.year = 2021;

// 포인터로 접근 (화살표 사용)
bagPtr->year = 2021;

 

이렇게 하면 저 포인터라는 녀석을 파라미터로 해서 함수를 만들 수 있습니다.

그게 void printBag(struct Bag * bag) 이 부분의 함수입니다.

void printBag(struct Bag *bag) {
    printf("Brand: %s\n", bag->brand);
    printf("Year: %d\n", bag->year);
    printf("Price: %.2f\n", bag->price);
}
```

이건 "구조체 포인터를 받아서, 그 안의 내용을 출력해주는 일꾼"입니다.

하나씩 뜯어볼게요:
```
void printBag(struct Bag *bag)
 │      │           │
 │      │           └─ "나한테 Bag의 주소를 알려줘, bag이라고 부를게"
 │      └─ 함수 이름
 └─ 돌려줄 값 없음 (그냥 출력만 할 거야)

 

 

주말코딩님의 프로필 이미지
주말코딩
지식공유자

자 이제 전체 흐름을 main 함수에서부터 읽어봅시다.

이제 전체 코드의 실행 순서를 따라가봅시다.

 

① 프로그램 시작

컴퓨터는 항상 main부터 실행합니다.

int main() { 부분에 가서 어떤 변수가 어떻게 만들어지는 지 보기

 

② 빈 가방을 하나 만들기

struct Bag myBag;

myBag (아직 비어있는 구조체)
┌──────────────────────────┐
│  brand : ???             │
│  year  : ???             │
│  price : ???             │
└──────────────────────────┘

 

③ 가방의 주소를 메모지(bagPtr)에 적어둠

struct Bag *bagPtr = &myBag;


bagPtr (메모지)            myBag (실제 가방)
┌────────────┐            ┌──────────────────────────┐
│  0x2000    │ ─────────→ │  brand : ???             │
└────────────┘            │  year  : ???             │
                          │  price : ???             │
                          └──────────────────────────┘

 

④ 포인터를 통해 가방에 값을 채워넣음

strcpy(bagPtr->brand, "Gucci");

bagPtr->year = 2021;

bagPtr->price = 1500.50;

bagPtr->brand은 "bagPtr이 가리키는 곳의 brand"이니까,

결국 myBag의 brand에 "Gucci"를 넣는 것입니다.

 

(메모리 주소는 임의로 쓴 것이니까 무시하세요.)


bagPtr (메모지)            myBag (값이 채워진 가방)
┌────────────┐            ┌──────────────────────────┐
│  0x2000    │ ─────────→ │  brand : "Gucci"         │
└────────────┘            │  year  : 2021            │
                          │  price : 1500.50         │
                          └──────────────────────────┘

 

⑤ printBag 함수를 호출

printBag(bagPtr); 이 한 줄이 실행되는 순간 일어나는 일:


main 함수
    │
    │  "야 printBag아, 가방 주소(bagPtr) 줄게. 출력 좀 해줘"
    │
    │  bagPtr (주소값 0x2000) 을 넘겨줌
    │
    ▼
printBag 함수가 받아서 실행
    │
    │  받은 주소를 bag 이라는 이름으로 사용
    │
    │  bag->brand  →  주소 따라가서 brand 읽음  →  "Gucci"
    │  bag->year   →  주소 따라가서 year 읽음   →  2021
    │  bag->price  →  주소 따라가서 price 읽음  →  1500.50
    │
    ▼
화면에 출력

 

⑥ 최종 출력결과

Brand: Gucci
Year: 2021
Price: 1500.50

 

⑦ 프로그램 종료

    return 0;
}

return 0은 "프로그램이 정상적으로 끝났어"라는 뜻입니다.

0

안녕하세요, 인프런 AI 인턴입니다. maritime23님.

구조체와 관련된 개념들이 처음에는 다소 복잡할 수 있습니다. 구조체 포인터와 이를 통한 함수 호출에 대해 간단히 설명드리고, 관련된 유용한 링크를 제공해 드리겠습니다.

구조체 포인터란?

  • 구조체 포인터는 구조체 자체가 아닌, 구조체가 저장된 메모리의 주소를 가리키는 포인터입니다. 즉, 구조체의 값이 아닌, 그 위치를 참조할 때 사용되는 도구입니다.
  struct Person {
      int age;
      float salary;
  };

위와 같은 구조체가 있으면, 구조체 포인터는 다음과 같이 선언할 수 있습니다:

  struct Person person1;
  struct Person* ptr = &person1;

여기서 ptrperson1의 메모리 주소를 가리킵니다.

구조체 포인터를 사용하여 함수 호출

  • 구조체 포인터를 함수에 전달하면, 함수가 구조체 자체가 아닌, 메모리 주소를 참조하게 됩니다. 이는 대용량 데이터를 다룰 때 복사 시간과 메모리를 절약하게 해줍니다.
  void updatePerson(struct Person* p) {
      p->age = 30;
  }

함수가 구조체 포인터를 매개변수로 받아들일 때는 접근 연산자로 ‘->‘를 사용하여 구조체 멤버에 접근합니다.

관련 내용을 더 살펴보시려면 다음 링크를 참고해 보세요:

  • C언어 구조체 관련 질문: 구조체 포인터와 사용 방법에 관한 설명이 담겨 있습니다.
  • 구조체 접근?: 구조체와 포인터를 활용하는 방법에 대한 다른 질문과 설명이 제공되어 있습니다.

이해에 어려움을 겪고 계신 점 충분히 이해합니다. 해당 링크에서 다양한 예제와 설명을 통해 개념을 더욱 쉽게 이해하실 수 있을 것입니다.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

maritime23님의 프로필 이미지
maritime23

작성한 질문수

질문하기