인프런 커뮤니티 질문&답변
아 진짜 구조체 이해 안되는데요
해결된 질문
작성
·
24
답변 3
0
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;
여기서 ptr은 person1의 메모리 주소를 가리킵니다.
구조체 포인터를 사용하여 함수 호출
- 구조체 포인터를 함수에 전달하면, 함수가 구조체 자체가 아닌, 메모리 주소를 참조하게 됩니다. 이는 대용량 데이터를 다룰 때 복사 시간과 메모리를 절약하게 해줍니다.
void updatePerson(struct Person* p) {
p->age = 30;
}
함수가 구조체 포인터를 매개변수로 받아들일 때는 접근 연산자로 ‘->‘를 사용하여 구조체 멤버에 접근합니다.
관련 내용을 더 살펴보시려면 다음 링크를 참고해 보세요:
- C언어 구조체 관련 질문: 구조체 포인터와 사용 방법에 관한 설명이 담겨 있습니다.
- 구조체 접근?: 구조체와 포인터를 활용하는 방법에 대한 다른 질문과 설명이 제공되어 있습니다.
이해에 어려움을 겪고 계신 점 충분히 이해합니다. 해당 링크에서 다양한 예제와 설명을 통해 개념을 더욱 쉽게 이해하실 수 있을 것입니다.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.





앞으로도 계속 어려울 수 있습니다.
많은 질문 부탁드립니다.