프로그래밍 언어/C++

[자료형(data type)] C++ 파생형 배열 총정리

순정법사 2023. 9. 8. 18:21
더보기
자료형 중 배열 공부 / https://ddanzimind.tistory.com/32

 

A. 배열

1. 1차원 배열

a. 배열이란?

🌟 같은 타입의 변수들로 이루어진 유한 집합

 

배열을 구성하는 각각의 값을 배열 요소라고 하며, 위치를 가리키는 숫자는 인덱스라고 함

인덱스는 0부터 시작 (양수만 가능)

 

같은 종류의 데이터를 많이 다뤄야 하는 경우 사용하는 가장 기본적인 자료구조

 

b. 1차원 배열

📘 문법

타입 배열이름[배열길이];

//타입 : 배열 요소로 들어가는 변수의 타입 명시
//배열 이름 : 배열이 선언된 후 배열로 접근하기 위해 사용
//배열의 길이 : 배열 요소의 갯수(생략하면 자동으로 설정됨)

 

💥 선언만 하고 초기화하지 않으면 쓰레기 값이 저장됨 (주의!)

 

⏳ 예제

#include <iostream>
using namespace std;

int main(void)
{
	int sum = 0;
	int grade[3];	// 길이가 3인 int형 배열 선언 
	
	// 인덱스를 이용한 배열의 초기화
	grade[0] = 85;	// 국어 점수 
	grade[1] = 65;	// 영어 점수 
	grade[2] = 90;	// 수학 점수 
	
	for (int i = 0; i < 3; i++)
	{
		sum += grade[i];	// 인덱스를 이용한 배열로의 접근 
	}
	
	cout << "국영수 과목 총 점수 합계는 " << sum << "점이고, 평균 점수는 " << (double)sum/3 <<"점입니다.";
	return 0;
}

✨ 실행결과

국영수 과목 총 점수 합계는 240점이고, 평균 점수는 80점입니다.

 

📝 예제 설명

 

위 예제의 배열 grade가 메모리 상에서 저장된 모습

 

배열의 이름은 첫 번째 요소와 같은 주소를 가리킴

 

c. 배열의 선언과 동시에 초기화

초기화 리스트(중괄호({})를 사용해 초깃값을 나열한 것)를 활용해 초기화 함

 

📘 문법

타입 배열이름[배열길이] = {배열요소1, 배열요소2, ...};

//배열 길이를 따로 입력 안하면 초기화 리스트 배열 요소의 개수에 맞춰 자동으로 설정

 

💙 초기화 리스트 초기화의 특징

 

  • 초기화 리스트 타입과 배열의 타입은 반드시 일치해야 함
  • 초기화 리스트를 이용한 초기화 방식은 선언과 함께 정의해야 함 (따로따로 X)
  • 초기화 리스트 개수 < 배열 총 길이 : 배열의 앞부터 차례대로 초기화 (나머지 0)
  • 초기화 리스트 개수 > 배열 총 길이 : 리스트 길이를 늘려버림 💥
  • 하나의 배열을 다른 배열에 대입 불가능 (길이가 같아도 X)

 

⏳ 예제

int arr1[3] = {0, 1, 2}; // 배열의 선언과 동시에 초기화 가능
int arr2[3];             // 배열의 선언
arr2[3] = {0, 1, 2};     // 배열이 먼저 선언된 후에는 이 방식으로 초기화 X (오류 발생)
arr2 = arr1;             // 길이가 같더라도 하나의 배열을 다른 배열에 통째로 대입 X (오류 발생)

 

⏳ 예제 : 배열을 선언과 동시에 초기화 리스트로 초기화

#include <iostream>
using namespace std;

int main(void)
{
	int sum = 0;
	int grade[3] = {85, 65, 90};	// 길이가 3인 int형 배열의 선언과 동시에 초기화
		
	for (int i = 0; i < 3; i++)
	{
		sum += grade[i];			// 인덱스를 이용한 배열의 접근 
	}
	
	cout << "국영수 과목 총 점수 합계는 " << sum << "점이고, 평균 점수는 " << (double)sum/3 <<"점입니다.";
	return 0;
}

✨ 실행결과

국영수 과목 총 점수 합계는 240점이고, 평균 점수는 80점입니다.

 

d. 배열의 특징

  • 배열의 길이를 선언할 때에는 반드시 상수를 사용
  • 배열 요소의 인덱스는 언제나 0부터 시작
  • C 컴파일러는 배열의 길이를 전혀 신경쓰지 않음 = 개발자가 직접 신경써야 함

 

⏳ 예제 : C++ 컴파일러는 배열의 길이를 신경쓰지 않음

#include <iostream>
using namespace std;

int main(void)
{
	int sum = 0;
	int grade[3] = {85, 65, 90};	// grade[0], grade[1], grade[2]만 선언 및 초기화 
	grade[3] = 100;					// grade[3]를 선언하지 않고 초기화 진행 
	
	for (int i = 0; i < 4; i++)		// grade[3]도 수식에 포함 
	{
		sum += grade[i];			// 인덱스를 이용한 배열의 접근 
	}
	
	cout << "국영수 과목 총 점수 합계는 " << sum << "점이고, 평균 점수는 " << (double)sum/3 <<"점입니다.";
	return 0;
}

✨ 실행결과

국영수 과목 총 점수 합계는 340점이고, 평균 점수는 113.333점입니다.

 

오류는 커녕 수식에서까지 이 배열 요소를 이용하여 결과까지 출력

💥 개발자가 전혀 의도하지 않은 결과물이기 때문에 예상치 못한 결과를 내줄 수 있음

 

🧡 불친절한 C++ 컴파일러

C++ 컴파일러는 일일이 배열의 길이 등 검사해 오류를 출력해주지 않음
따라서 이런 계산을 직접 개발자가 해야 함

 

e. 배열이 차지하는 메모리의 크기 

배열을 복사하거나 배열 요소에 특정 작업을 하고 싶을 때는 해당 배열이 차지하는 메모리의 크기를 정확히 알아야 함

 

1) 배열이 차지하는 총 메모리의 크기 구하기 

 

📘 문법

배열이 차지하는 메모리의 크기 = 배열의 길이 X sizeof(타입)

 

2) 배열의 길이 구하기

 

📘 문법

배열의 길이 = sizeof(배열 이름) / sizeof(배열 이름[0])

//배열 이름[0] : 해당 배열의 타입을 표현하기 위해서 사용

 

⏳ 예제

#include <iostream>
using namespace std;

int main(void)
{
	int grade[] = {85, 65, 90};					// 배열의 길이를 명시하지 않음 
	int len = sizeof(grade) / sizeof(grade[0]);	// 배열의 길이를 구하는 공식 
	
	cout << "배열 grade의 길이는 " << len << "입니다.";
	return 0;
}

✨ 실행결과

배열 grade의 길이는 3입니다.

 

f. C++11에서의 배열 초기화

  • 배열을 초기화할 때에 대입 연산자(=)를 사용하지 않아도 됨
  • 값을 명시하지 않고 괄호({})만을 사용하여 초기화하면, 모든 배열 요소를 0으로 초기화할 수 있음
  • 초기화 리스트를 사용하여 배열을 초기화할 경우에는 narrowing cast X
  • array 템플릿 클래스가 추가

 

g. narrowing cast

🌟 초기화를 통해 발생하는 암시적인 데이터의 손실

 

int var = 3.14; // narrowing cast 발생

 

이전 버전의 C++에서 발생하던 수많은 호환성 문제를 C++11에서는 초기화 리스트를 사용하여 방지함

C++11에서는 초기화 리스트를 사용해 변수나 배열을 초기화할 경우 ➡ narrowing cast를 허용 X  ➡ 경고 발생

 

int var = {3.14}; 
// 초기화 리스트를 통한 narrowing cast는 허용하지 않으므로, 경고를 발생시킴.

 

👉 초기화 리스트를 이용하여 이러한 narrowing cast로 인한 데이터의 손실 및 호환성 문제를 미리 방지

 

 

2. 다차원 배열 (multi-dimensional array)

a. 다차원 배열이란?

🌟 2차원 이상의 배열을 의미하며, 배열 요소로 또 다른 배열을 가지는 배열

 

b. 2차원 배열 (two dimensional array)

🌟배열의 요소로 1차원 배열을 가지는 배열

 

📘 문법

타입 배열이름[행의길이][열의길이];

//타입 : 배열 요소로 저장되는 변수의 타입
//배열 이름 : 배열이 선언 된 후 배열에 접근하기 위해 사용
//행의 길이 : 생략 가능 
//열의 길이 : 생략 불가능 (생략시 컴파일 오류)

 

2차원 배열을 나타내는 타입을 따로 제공하지는 않고

1차원 배열의 요소로 1차원 배열을 사용해 나타냄 (다른 다차원 배열도 같음)

 

🎨 도식화

 

 

도식화 하면 위와같은 그림이지만, 메모리는 선형공간이기 때문에 실제론 아래와 같이 표현

 

 

int arr01[6] = {10, 20, 30, 40, 50, 60};

int arr02[2][3] = {10, 20, 30, 40, 50, 60};

 

c. 2차원 배열의 선언과 동시에 초기화

1차원 배열과 마찬가지로 선언과 동시에 초기화 가능

3가지 방법으로 초기화 할 수 있음

 

1) 1차원 배열의 초기화 형태를 따르는 방식

 

2차원 배열의 배열 요소[0][0]부터 차례대로 초기화

요소의 개수가 총 길이보다 적으면, 나머지 배열 요소는 모두 0으로 초기화

 

📘 문법

타입 배열이름[행의길이][열의길이] = {배열요소[0][0], 배열요소[0][1], ..., 배열요소[1][0], 배열요소[1][1], ..., 배열요소[2][0], 배열요소[2][1], ...};

 

2) 배열의 모든 요소를 초기화하는 방식

 

📘 문법

타입 배열이름[행의길이][열의길이] =
{
    {배열요소[0][0], 배열요소[0][1], ...},
    {배열요소[1][0], 배열요소[1][1], ...},
    {배열요소[2][0], 배열요소[2][1], ...},
    ...
};

 

👉 1) 번 방식과 방식과 결과는 똑같지만 좀 더 직관적이여서 이 방식을 많이 사용함

 

🤓 예제

int arr1[2][3] = {10, 20, 30, 40};

int arr2[2][3] = {
    {10, 20, 30},
    {40, 50, 60}
};

 

3) 배열의 일부 요소만을 초기화하는 방식

 

초기화하지 않은 배열 요소는 모두 0으로 자동초기화

 

🤓 예제

#include <iostream>
#include <iomanip>
using namespace std;

int main(void)
{
	int arr_col_len, arr_row_len;
	int arr[3][4] = {
		{10, 20},
		{30, 40, 50, 60},
		{0, 0, 70, 80}
	};
	
	arr_col_len = sizeof(arr[0]) / sizeof(arr[0][0]);				// 2차원 배열의 열의 길이를 계산함 
	arr_row_len = (sizeof(arr) / arr_col_len) / sizeof(arr[0][0]);	// 2차원 배열의 행의 길이를 계산함 
			
	cout << "arr의 배열 요소의 값" << endl;
	for (int i = 0; i < arr_row_len; i++)
	{
		for (int j = 0; j < arr_col_len; j++)
		{
			cout << setw(4) << arr[i][j];
		}
		cout << endl;
	}
	return 0;
}

✨ 실행결과

arr의 배열 요소의 값
  10  20   0   0
  30  40  50  60
   0   0  70  80

 

d.  2차원 배열의 길이 구하기

1) 2차원 배열 열의 길이 구하기

 

📘 문법

arr_col_len = sizeof(arr[0]) / sizeof(arr[0][0]); 
// 2차원 배열의 열의 길이를 계산함

 

2) 2차원 배열 행의 길이 구하기

 

sizeof(arr[0])으로 먼저 2차원 배열의 한 행의 길이를 구한 후에, 그 값을 배열 타입의 크기로 나누어서 구함

 

📘 문법

arr_row_len = (sizeof(arr) / arr_col_len) / sizeof(arr[0][0]); 
// 2차원 배열의 행의 길이를 계산함
// arr_row_len = 열의 길이 / 배열 타입의 크기

 

e. 배열의 길이 자동 설정

1차원 배열과 마찬가지로 2차원 배열도 배열의 길이를 명시하지 않고, 자동으로 배열의 길이를 설정할 수 있음

 

행의 길이를 생략하면 자동으로 길이를 설정 (행만 가능)

 

⏳ 예제

#include <iostream>
#include <iomanip>
using namespace std;

int main(void)
{
	int arr_col_len, arr_row_len;
	//int arr[3][] = {
	int arr[][4] = {
		{10, 20},
		{30, 40, 50, 60},
		{0, 0, 70, 80}
	};
	
	arr_col_len = sizeof(arr[0]) / sizeof(arr[0][0]);				// 2차원 배열의 열의 길이를 계산함 
	arr_row_len = (sizeof(arr) / arr_col_len) / sizeof(arr[0][0]);	// 2차원 배열의 행의 길이를 계산함 
			
	cout << "arr의 배열 요소의 값" << endl;
	for (int i = 0; i < arr_row_len; i++)
	{
		for (int j = 0; j < arr_col_len; j++)
		{
			cout << setw(4) << arr[i][j];
		}
		cout << endl;
	}
	return 0;
}

✨ 실행결과

arr의 배열 요소의 값
  10  20   0   0
  30  40  50  60
   0   0  70  80

 

 

 


출처 : http://www.tcpschool.com/cpp/cpp_arrayPointer_oneDimensional

 

코딩교육 티씨피스쿨

4차산업혁명, 코딩교육, 소프트웨어교육, 코딩기초, SW코딩, 기초코딩부터 자바 파이썬 등

tcpschool.com