배열(Array)이란 같은 타입의 데이터들을 모아둔 집합소입니다.
여러 개의 변수를 개별적으로 선언하는 것보다 배열을 사용하면 관리와 접근이 더 효율적입니다.
📌 배열 선언 기본 문법
타입 배열이름[크기];
예제:
int numbers[5]; // 5개의 정수형 데이터를 저장할 수 있는 배열
StatInfo 구조체 정의#include <iostream>
using namespace std;
// 구조체 정의
struct StatInfo {
int hp = 0xAAAAAAAA;
int attack = 0xBBBBBBBB;
int defence = 0xCCCCCCCC;
};
StatInfo 구조체는 체력(hp), 공격력(attack), 방어력(defence)을 저장하는 구조체입니다.0xAAAAAAAA, 0xBBBBBBBB, 0xCCCCCCCC을 설정하여int main() {
// 몬스터 개수 정의 (배열 크기)
const int monsterCount = 10;
// StatInfo 배열 선언 (10개의 몬스터 저장)
StatInfo monsters[monsterCount];
monsterCount)는 const int로 선언해야 컴파일러가 크기를 인식할 수 있습니다.monsters[monsterCount]는 10개의 StatInfo 구조체를 저장할 수 있습니다.📍 배열 메모리 구조 예시
| 인덱스 | 변수명 | 주소 예시 | 데이터 |
|------|------|------|------|
| 0 | monsters[0] | 0x1000 | { hp: ?, attack: ?, defence: ? } |
| 1 | monsters[1] | 0x100C | { hp: ?, attack: ?, defence: ? } |
| 2 | monsters[2] | 0x1018 | { hp: ?, attack: ?, defence: ? } |
| ... | ... | ... | ... |
int a = 10;
int b = a; // b에 a의 값(10) 복사
✅ 변수는 하나의 값을 저장하는 공간
✅ b = a; 는 a의 값을 b에 복사하는 과정
✅ 배열은 같은 타입의 여러 데이터를 저장하는 구조
StatInfo players[10];
// players = monsters; // ❌ 불가능 (배열은 직접 복사할 수 없음)
📌 배열은 단순한 변수와 다르게 직접 대입(=)이 불가능합니다.
➡ 배열을 복사하려면 반복문을 사용해야 합니다.
auto WhoAmI = monsters; // 첫 번째 원소를 가리키는 포인터
StatInfo* monster_0 = monsters; // monsters[0]을 가리키는 포인터
monsters)은 첫 번째 원소의 주소를 가리키는 포인터로 해석됩니다.WhoAmI의 타입은 StatInfo*이며, monsters[0]의 주소를 저장합니다.monster_0을 사용하여 첫 번째 원소에 접근할 수 있습니다.monster_0->hp = 100;
monster_0->attack = 10;
monster_0->defence = 1;
✅ monster_0이 monsters[0]을 가리키므로 -> 연산자로 접근 가능
✅ monsters[0]의 hp, attack, defence 값을 수정
StatInfo* monster_1 = monsters + 1; // monsters[1]을 가리키는 포인터
monster_1->hp = 200;
monster_1->attack = 20;
monster_1->defence = 2;
✅ 포인터 산술 연산을 사용하여 배열의 다음 원소(monsters[1])를 가리킴
✅ monsters + 1은 sizeof(StatInfo)만큼 이동하여 두 번째 원소(monsters[1])를 가리킴
📌 포인터 이동 예시
StatInfo* p = monsters;
p = p + 1; // 다음 원소로 이동 (monsters[1]을 가리킴)
StatInfo& monster_2 = *(monsters + 2);
monster_2.hp = 300;
monster_2.attack = 30;
monster_2.defence = 3;
✅ monsters + 2를 역참조(*)하여 monsters[2]를 참조
✅ 참조(&)를 사용하면 별도의 포인터 없이 원본 데이터 수정 가능
📌 포인터와 참조의 차이
StatInfo* p = &monsters[2]; // 포인터 사용
p->hp = 300;
StatInfo& ref = monsters[2]; // 참조 사용
ref.hp = 300;
➡ 참조는 직접 원본을 가리키지만, 포인터는 주소를 저장하는 별도 변수가 필요합니다.
for (int i = 0; i < monsterCount; i++) {
monsters[i].hp = 100 * (i + 1);
monsters[i].attack = 10 * (i + 1);
monsters[i].defence = (i + 1);
}
✅ 반복문을 사용하여 배열을 자동으로 초기화
✅ monsters[i]를 사용하면 *(monsters + i)와 동일한 효과
📌 배열 접근 방식
monsters[i].hp = 100; // 일반적인 배열 접근 방식
(*(monsters + i)).hp = 100; // 포인터 연산을 이용한 접근 방식
➡ 포인터 연산보다 배열 인덱스(monsters[i])가 가독성이 좋음
int numbers[5] = {}; // 모든 요소를 0으로 초기화
int numbers1[10] = {1,2,3,4,5}; // 앞부분만 초기화, 나머지는 0
int numbers2[] = {1,2,3,4,11,24,124,14,1}; // 크기를 자동으로 결정
✅ {} 사용 시 모든 원소를 0으로 초기화
✅ 초기화되지 않은 부분은 기본값(정수는 0)으로 채워짐
✅ 배열 크기를 명시하지 않으면 자동으로 결정됨
char helloStr[] = {'H', 'e', 'l', 'l', 'o', '\0'};
cout << helloStr << endl;
✅ char 배열의 마지막에는 널 종료 문자(\0)가 필요
✅ 문자열 리터럴 초기화 가능
char hello[] = "Hello"; // 자동으로 \0이 포함됨