C언어 이론 정리 - 06

Lee Pil Ung·2021년 12월 6일
0

C

목록 보기
6/6
post-thumbnail

📖 C언어 이론 정리 - 06

C언어 이론 정리 파트 06
자료 참조 : TCP School.com

- 1차원 배열(array)

배열배열(array) 이란?

배열(array)은 같은 타입의 변수들로 이루어진 유한 집합으로 정의된다.

배열을 구성하는 각각의 값을 배열 요소(element)라고 하며, 배열에서의 위치를 가리키는 숫자는 인덱스(index)라고 한다.

C언어에서 인덱스는 언제나 0부터 시작하며, 0을 포함한 양의 정수만을 가질 수 있다.

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

배열은 선언되는 형식에 따라 1차원 배열, 2차원 배열뿐만 아니라 그 이상의 다차원 배열로도 선언할 수 있다.

하지만 현실적으로 이해하기가 쉬운 2차원 배열까지가 많이 사용된다.

1차원 배열

1차원 배열은 가장 기본적인 배열로 다음과 같은 문법에 따라 선언된다.

✅ 문법

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

타입은 배열 요소로 들어가는 변수의 타입을 명시한다.

배열 이름은 배열이 선언된 후에 배열로 접근하기 위해 사용된다.

배열의 길이는 해당 배열이 몇 개의 배열 요소를 가지게 되는지 명시한다.

  • 🚩 C언어에서는 배열을 선언만 하고 초기화하지 않으면, 각 배열 요소에 아무런 의미를 가지지 않는 쓰레기값이 저장되어 있게 된다. 따라서 초기화되지 않은 배열은 사용하지 않도록 주의를 기울여야 한다.

📝 예제

#include <stdio.h>

int main(void)
{
  int i;
  int sum = 0;
  int grade[3];        // 길이가 3인 int형 배열 선언

  /* 배열의 초기화 */
  grade[0] = 85;       // 국어 점수
  grade[1] = 65;       // 영어 점수
  grade[2] = 90;       // 수학 점수

  for (i = 0; i < 3; i++)
  {
      sum += grade[i]; // 인덱스를 이용한 배열의 접근
  }
  printf("국영수 과목 총 점수 합계는 %d점이고, 평균 점수는 %f점입니다.\n", sum, (double)sum/3);
}
// 실행 결과
국영수 과목 총 점수 합계는 240점이고, 평균 점수는 80.000000점입니다.

위의 예제에서 길이가 3인 int형 배열을 선언했다.(int grade[3];)

또한, 0부터 시작하는 인덱스(index)를 이용하면 각각의 배열 요소에 따로 접근할 수 있다.

다음 그림은 위의 예제에서 사용된 배열 grade가 메모리 상에서 어떻게 저장되는지를 보여준다.

위 그림처럼 언제나 배열의 이름은 배열의 첫 번째 요소와 같은 주소를 가리키고 있다.

배열의 선언과 동시에 초기화 하는 방법

C언어에서는 변수와 마찬가지로 배열도 선언과 동시에 초기화할 수 있다.

다음과 같이 중괄호({})를 사용하여 초깃값을 나열한 것을 초기화 리스트라고 한다.

✅ 문법

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

단, 초기화 리스트의 타입과 배열의 타입은 반드시 일치해야 한다.

만약에 초기화 리스트의 개수가 배열의 총 길이보다 적으면, 배열의 앞에서부터 차례대로 초기화된다.

이때 초기화되지 못한 나머지 배열 요소는 모두 0으로 자동 초기화된다.

초기화 리스트의 개수가 배열의 길이보다 길 경우에는 아래 배열의 특징에서 따로 다루도록 한다.

다음 예제는 앞선 예제와 같은 배열을 선언과 동시에 초기화하는 예제이다.

📝 예제

int i;
int sum = 0;
int grade[3] = {85, 65, 90}; // 길이가 3인 int형 배열의 선언과 동시에 초기화

for (i = 0; i < 3; i++)
{
    sum += grade[i];
}
printf("국영수 과목 총 점수 합계는 %d이고, 평균 점수는 %f입니다.\n", sum, (double)(sum/3));
// 실행 결과
국영수 과목 총 점수 합계는 240이고, 평균 점수는 80.000000입니다.

배열의 길이 자동 설정

C언어에서는 초기화 리스트에 맞춰 자동으로 배열의 길이를 설정할 수도 있다.

다음과 같이 배열의 길이를 따로 입력하지 않은 배열은 초기화 리스트의 배열 요소의 개수에 맞춰 자동으로 배열의 길이가 설정된다.

✅ 문법

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

다음 예제에서 int형 배열 arr의 길이는 자동으로 3으로 설정됨과 동시에 초기화 리스트에 의해 초기화된다.

📝 예제

int arr[] = {1, 2, 3};

배열의 특징

C언어에서 배열은 다음과 같은 특징을 가진다.

  1. 배열의 길이를 선언할 때에는 반드시 상수를 사용해야 한다.

  2. 배열 요소의 인덱스는 언제나 0부터 시작한다.

  3. C 컴파일러는 배열의 길이를 전혀 신경 쓰지 않는다.

📝 예제

#include <stdio.h>

int main(void)
{
  int i;
  int sum = 0;
  int grade[3] = {85, 65, 90}; // grade[0], grade[1], grade[2]만 선언 및 초기화
  grade[3] = 100;              // grade[3]를 선언하지 않고 초기화 진행

  for (i = 0; i < 4; i++)      // grade[3]도 수식에 포함
  {
      sum += grade[i];
  }
  printf("국영수 과목 총 점수 합계는 %d이고, 평균 점수는 %f입니다.\n", sum, (double)sum/3);
}
// 실행 결과
국영수 과목 총 점수 합계는 340이고, 평균 점수는 113.333333입니다.

위의 예제에서는 크기가 3인 int형 배열 grade를 선언하고 있다.

즉, 배열 grade의 배열 요소는 grade[0], grade[1], grade[2]만이 존재한다.

하지만 존재하지도 않는 grade[3]이라는 배열 요소의 초기화를 진행하고, 반복문을 통해 수식에서도 이용한다.

이때 C 컴파일러는 오류는커녕 수식에서까지 이 배열 요소를 이용하여 결과를 출력한다.

하지만 이 결과는 개발자가 전혀 의도하지 않은 결과물이며, 이러한 프로그램은 종종 예상치 못한 결과를 내주기도 한다.

  • 🚩위와 같이 C언어에서는 컴파일러가 일일이 배열의 길이 등을 검사하여 오류를 출력해 주지 않는다. 따라서 C언어로 프로그래밍할 때에는 이런 계산을 언제나 개발자가 직접 신경 써야 한다.

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

C언어에서 배열을 복사하거나 배열 요소에 특정 작업을 하고 싶을 때는 해당 배열이 차지하는 메모리의 크기를 정확히 알고 있어야만 한다.

배열이 차지하는 총 메모리의 크기는 다음 수식을 사용하여 구할 수 있다.

✅ 메모리의 크기 수식

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

배열의 길이를 알고 싶을 때에는 다음 수식을 사용하여 구할 수 있다.

✅ 배열의 길이 수식

배열의 길이 = sizeof(배열 이름) / sizeof(배열 이름[0])
  • 🚩 위의 수식에서 배열 이름[0]은 해당 배열의 타입을 표현하기 위해서 사용되었다.

📝 예제

다음 예제는 앞서 살펴본 수식을 이용하여 배열의 길이는 구하는 예제이다.

#include <stdio.h>

int main(void)
{
  int grade[] = {85, 65, 90};                     // 배열의 길이를 명시하지 않음
  int arr_len = sizeof(grade) / sizeof(grade[0]); // 배열의 길이를 구하는 공식

  printf("배열 arrGrade의 길이는 %d입니다.\n", arr_len);
}
// 실행 결과
배열 grade의 길이는 3입니다.

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

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

즉, 2차원 배열은 배열 요소로 1차원 배열을 가지는 배열이며, 3차원 배열은 배열 요소로 2차원 배열을 가지는 배열이고, 4차원 배열은 배열 요소로 3차원 배열을 가지는 배열인 것이다.

2차원 배열(two dimensional array)

2차원 배열이란 배열의 요소로 1차원 배열을 가지는 배열이다.

C언어에서는 2차원 배열을 나타내는 타입을 따로 제공하지 않는다.

대신에 1차원 배열의 배열 요소로 또 다른 1차원 배열을 사용하여 2차원 배열을 나타낼 수 있다.

2차원 배열은 다음과 같은 문법에 따라 선언할 수 있다.

✅ 문법

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

타입은 배열 요소로 저장되는 변수의 타입을 설정한다.

배열 이름은 배열이 선언된 후에 배열에 접근하기 위해 사용된다.

다음 그림은 2차원 배열을 이해하기 쉽도록 도식적으로 표현한 그림이다.

하지만 컴퓨터의 메모리는 위와 같은 입체적 공간이 아닌 선형 공간이므로 실제로는 다음 그림과 같이 저장된다.

📝 예제

#include <stdio.h>

int main(void)
{
	int arr01[6] = {10, 20, 30, 40, 50, 60};
	int arr02[2][3] = {10, 20, 30, 40, 50, 60};

	printf("arr01의 배열 요소의 값\n");
	printf("%d %d %d %d %d %d\n", arr01[0], arr01[1], arr01[2], arr01[3], arr01[4], arr01[5]);
	printf("arr02의 배열 요소의 값\n");
	printf("%d %d %d %d %d %d\n", arr02[0][0], arr02[0][1], arr02[0][2], arr02[1][0], arr02[1][1], arr02[1][2]);
	return 0;
}
// 실행 결과
arr01의 배열 요소의 값
10 20 30 40 50 60
arr02의 배열 요소의 값
10 20 30 40 50 60

배열의 선언과 동시에 초기화하는 방법

1차원 배열과 마찬가지로 2차원 배열도 선언과 동시에 초기화할 수 있다.

2차원 배열은 1차원 배열과는 달리 여러 방식으로 초기화할 수 있다.

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

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

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

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

C언어에서는 2차원 배열을 1차원 배열의 초기화 형태로도 초기화할 수 있다.

✅ 문법

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

이 방식으로는 2차원 배열의 배열 요소[0][0]부터 차례대로 초기화된다.

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

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

C언어에서는 2차원 배열의 모든 요소를 초기화할 수 있다.

✅ 문법

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

이 방식은 앞서 살펴본 1차원 배열의 초기화 형태를 따르는 방식과 결과는 똑같다.

하지만 좀 더 직관적으로 2차원 배열의 모습을 알 수 있으므로 보통 이 방식을 가장 많이 사용한다.

📝 예제

다음 예제는 앞서 살펴본 두 가지 방식을 각각 사용하여 배열을 선언하고 초기화하는 예제이다.

#include <stdio.h>

int main(void)
{
	int arr01[2][3] = {10, 20, 30, 40, 50,60};
	int arr02[2][3] = {
		{10, 20, 30},
		{40, 50, 60}
	};

	printf("arr01의 배열 요소의 값\n");
	printf("%d %d %d %d %d %d\n", arr01[0][0], arr01[0][1], arr01[0][2], arr01[1][0], arr01[1][1], arr01[1][2]);
	printf("arr02의 배열 요소의 값\n");
	printf("%d %d %d %d %d %d\n", arr02[0][0], arr02[0][1], arr02[0][2], arr02[1][0], arr02[1][1], arr02[1][2]);
	return 0;
}
// 실행 결과
arr01의 배열 요소의 값
10 20 30 40 50 60
arr02의 배열 요소의 값
10 20 30 40 50 60

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

C언어에서는 2차원 배열의 일부 요소만을 초기화할 수도 있다.

이 방식으로는 다음 예제와 같이 2차원 배열의 원하는 배열 요소만을 초기화할 수 있다.

이때 초기화하지 않은 배열 요소는 모두 0으로 자동 초기화된다.

📝 예제

#include <stdio.h>

int main(void)
{
	int i, j, 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차원 배열의 행의 길이를 계산함

	/* 2차원 배열의 출력 */
	for (i = 0; i < arr_row_len; i++)
	{
		for (j = 0; j < arr_col_len; j++)
		{
			printf("%4d", arr[i][j]);
		}
		printf("\n");
	}

	return 0;
}
// 실행 결과
10  20   0   0
30  40  50  60
 0   0  70  80

위의 예제에서 2차원 배열 열의 길이를 구할 때 사용하는 수식은 다음과 같다.

✅ 열의 길이 수식

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

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

열의 길이를 이용하면 2차원 배열 행의 길이도 구할 수 있다.

✅ 행의 길이 수식

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

배열의 길이 자동 설정

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

단, 열의 길이는 생략할 수 있지만, 행의 길이는 반드시 명시해야 한다.

📝 예제

다음 예제는 앞선 예제에서 열의 길이를 생략한 예제로, 같은 결과를 출력한다.

#include <stdio.h>

int main(void)
{
	int i, j, arr_col_len, arr_row_len;
	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차원 배열의 행의 길이를 계산함

	/* 2차원 배열의 출력 */
	for (i=0; i<arr_row_len; i++)
	{
		for (j=0; j<arr_col_len; j++)
		{
			printf("%4d", arr[i][j]);
		}
		printf("\n");
	}

	return 0;
}
// 실행 결과
10  20   0   0
30  40  50  60
 0   0  70  80

profile
Frontend SoftWare Engineer(2022.06.27 ~)

0개의 댓글