C 언어의 주요 데이터 타입과 그 사용법

목차

도입 문구


C 언어는 다양한 데이터 타입을 제공하여 개발자가 여러 유형의 데이터를 처리할 수 있게 돕습니다. 데이터 타입은 프로그램에서 변수에 저장되는 값의 종류와 크기를 정의하는 중요한 요소입니다. C 언어에서 제공하는 기본적인 데이터 타입을 이해하는 것은 효율적인 프로그래밍의 기초가 됩니다. 본 기사에서는 C 언어에서 자주 사용되는 주요 데이터 타입과 그 사용법을 자세히 설명합니다.

기본 데이터 타입


C 언어의 기본 데이터 타입은 프로그램에서 사용하는 값의 종류와 크기를 결정합니다. 주요 기본 데이터 타입으로는 int, char, float, double이 있으며, 각각은 특정 용도에 맞게 데이터를 처리하는 데 사용됩니다.

정수형 (int)


int는 정수를 저장하는 데 사용되는 데이터 타입으로, 보통 4바이트 크기를 가집니다. 값의 범위는 시스템에 따라 달라질 수 있지만, 일반적으로 -2,147,483,648에서 2,147,483,647까지의 값을 저장할 수 있습니다. 정수 계산 및 반복문에서 주로 사용됩니다.

문자형 (char)


char는 한 개의 문자를 저장하는 데이터 타입으로, 1바이트 크기를 가집니다. char 변수는 ASCII 값으로 문자를 저장하며, 문자형 변수는 숫자처럼 취급되어 연산에도 사용될 수 있습니다. 예를 들어, char c = 'A';와 같이 사용합니다.

실수형 (float, double)


float는 단정도 부동소수점 숫자를 저장하는 데이터 타입으로, 보통 4바이트 크기를 가집니다. 실수 계산에서 사용되며, 정확한 값의 범위나 정밀도가 중요할 때는 double을 사용합니다. double은 더 넓은 범위와 높은 정밀도를 제공하며, 보통 8바이트 크기를 가집니다.

배열형 (void)


void는 특정 값을 가지지 않는 데이터 타입으로, 함수에서 반환 타입으로 주로 사용됩니다. void는 메모리를 차지하지 않으며, 함수가 아무런 값을 반환하지 않을 때 사용됩니다.

정수형 데이터 타입


C 언어에서 정수형 데이터 타입은 주로 숫자 값을 처리할 때 사용됩니다. 정수형 데이터 타입에는 int, short, long, long long 등이 있으며, 각각은 저장할 수 있는 값의 범위와 메모리 크기가 다릅니다. 이러한 차이를 이해하고 적절하게 선택하는 것이 중요합니다.

int


int는 C 언어에서 가장 기본적인 정수형 데이터 타입입니다. 일반적으로 4바이트 크기를 가지며, -2,147,483,648에서 2,147,483,647까지의 값을 저장할 수 있습니다. int는 기본적인 정수 연산에 널리 사용됩니다.

short


shortint보다 작은 범위의 정수를 저장하는 데 사용됩니다. 보통 2바이트 크기를 가지며, -32,768에서 32,767까지의 값을 저장할 수 있습니다. short는 메모리 공간을 절약해야 할 때 사용됩니다.

long


longint보다 더 큰 범위의 정수를 저장하는 데 사용됩니다. 보통 4바이트 또는 8바이트 크기를 가지며, -2,147,483,648에서 2,147,483,647 또는 그보다 더 넓은 범위의 값을 저장할 수 있습니다. 정수 계산에서 더 큰 범위가 필요한 경우 사용됩니다.

long long


long longlong보다 더 큰 정수 값을 저장할 수 있습니다. 보통 8바이트 크기를 가지며, -9,223,372,036,854,775,808에서 9,223,372,036,854,775,807까지의 값을 저장할 수 있습니다. 매우 큰 정수 값이 필요한 경우 long long을 사용합니다.

정수형 예시


다음은 각 정수형 데이터 타입을 사용하는 예시입니다.

#include <stdio.h>

int main() {
    int a = 100;
    short b = 32767;
    long c = 1000000000;
    long long d = 123456789012345LL;

    printf("int: %d\n", a);
    printf("short: %hd\n", b);
    printf("long: %ld\n", c);
    printf("long long: %lld\n", d);

    return 0;
}

위 코드에서 int, short, long, long long을 선언하고 각각 출력합니다. long long을 사용할 때는 LL 접미사를 붙여야 한다는 점을 유의해야 합니다.

실수형 데이터 타입


C 언어에서 실수형 데이터 타입은 소수점이 포함된 숫자를 처리하는 데 사용됩니다. 실수형 데이터 타입에는 float, double, long double이 있으며, 각 타입은 저장할 수 있는 값의 범위와 정확도에서 차이를 보입니다. 이를 이해하고 적절한 실수형을 선택하는 것이 중요합니다.

float


float는 단정도 부동소수점 숫자를 저장하는 데 사용됩니다. 일반적으로 4바이트 크기를 가지며, 대략 6~7자리 정도의 정확도를 제공합니다. float는 메모리 크기가 작고, 성능을 고려해야 할 때 적합합니다. 하지만 계산의 정확도가 중요한 경우 double을 사용해야 할 수 있습니다.

#include <stdio.h>

int main() {
    float num = 3.14159;
    printf("float 값: %.6f\n", num);  // 소수점 6자리까지 출력
    return 0;
}

위 코드는 float 타입을 사용하여 원주율 값을 출력하는 예시입니다. %.6f는 소수점 이하 6자리까지 출력하라는 뜻입니다.

double


double은 두 배 더 큰 크기의 실수형으로, 보통 8바이트 크기를 가집니다. doublefloat보다 더 높은 정확도(대략 15~16자리)와 더 넓은 범위의 실수를 저장할 수 있습니다. 대부분의 실수 계산에서 double을 사용하는 것이 일반적입니다.

#include <stdio.h>

int main() {
    double num = 3.141592653589793;
    printf("double 값: %.15f\n", num);  // 소수점 15자리까지 출력
    return 0;
}

double 타입을 사용하여 보다 정확한 값을 출력하는 예시입니다. %.15f는 소수점 이하 15자리까지 출력하도록 설정한 것입니다.

long double


long doubledouble보다 더 큰 크기와 더 높은 정확도를 제공하는 실수형입니다. 보통 8바이트 이상이며, 일부 시스템에서는 12바이트 또는 16바이트까지 지원합니다. 매우 높은 정밀도가 필요한 과학적 계산에서 사용됩니다.

#include <stdio.h>

int main() {
    long double num = 3.14159265358979323846;
    printf("long double 값: %.20Lf\n", num);  // 소수점 20자리까지 출력
    return 0;
}

위 코드는 long double을 사용하여 높은 정밀도의 값을 출력하는 예시입니다. %.20Lf는 소수점 이하 20자리까지 출력하도록 설정한 것입니다.

실수형 데이터 타입 비교

데이터 타입크기정확도예시 값
float4바이트약 6~7자리3.14159
double8바이트약 15~16자리3.141592653589793
long double8바이트 이상약 20자리 이상3.14159265358979323846

위 표는 각 실수형 데이터 타입의 크기, 정확도, 예시 값을 비교한 것입니다. 계산의 정확도나 범위가 중요한 경우, double이나 long double을 선택하는 것이 적합합니다.

문자형 데이터 타입


C 언어에서 char는 한 개의 문자를 저장하는 데 사용되는 데이터 타입입니다. char는 1바이트 크기를 가지며, 주로 텍스트 데이터를 처리할 때 사용됩니다. char는 문자 하나를 저장하는 데 사용되지만, 내부적으로는 해당 문자의 ASCII 코드 값을 저장합니다. 이로 인해 문자형 데이터는 숫자처럼 처리될 수 있으며, 연산이 가능하기도 합니다.

char 기본 사용법


char는 문자 하나를 저장할 수 있는 데이터 타입으로, 작은따옴표(')로 문자 값을 정의합니다. 예를 들어, char c = 'A';c 변수에 문자 ‘A’를 저장합니다.

#include <stdio.h>

int main() {
    char c = 'A';  // 문자 A 저장
    printf("문자: %c\n", c);  // 문자 출력
    return 0;
}

위 코드는 char 타입을 사용하여 문자 ‘A’를 저장하고 출력하는 예시입니다. %cprintf에서 문자를 출력할 때 사용되는 서식 지정자입니다.

ASCII 코드와 문자형


char는 문자에 대응하는 ASCII 코드 값을 내부적으로 저장합니다. 예를 들어, ‘A’는 ASCII 코드 값 65에 대응하고, ‘B’는 66에 대응합니다. char 타입의 변수에 숫자를 저장하면 해당 ASCII 코드에 해당하는 문자가 출력됩니다.

#include <stdio.h>

int main() {
    char c = 65;  // ASCII 코드 65는 'A'
    printf("문자: %c\n", c);  // 문자 A 출력
    return 0;
}

이 예시에서는 65를 저장했으므로, 출력은 ‘A’가 됩니다. char는 문자뿐만 아니라 숫자처럼 연산에 사용될 수 있기 때문에, 문자와 숫자 간의 변환이 가능합니다.

문자형 연산


char는 실제로 숫자로 취급될 수 있어 문자 간의 연산도 가능합니다. 예를 들어, ‘A’와 ‘B’를 더하면 두 문자의 ASCII 코드 값이 더해지며, 그 결과는 새로운 문자로 변환됩니다.

#include <stdio.h>

int main() {
    char a = 'A';
    char b = 'B';
    char sum = a + b;  // ASCII 코드 값 65 + 66 = 131
    printf("두 문자의 합: %c\n", sum);  // 출력: 문자 131
    return 0;
}

이 코드에서 a + b는 ‘A’와 ‘B’의 ASCII 코드 값(65 + 66 = 131)을 더한 결과입니다. 131은 ASCII 코드표에서 정의된 문자에 해당하지 않지만, 이처럼 문자형은 숫자처럼 연산할 수 있습니다.

문자형의 유용성


char는 주로 문자열을 처리할 때 사용되며, 여러 개의 char 변수들이 모여 문자열을 형성합니다. 또한, char 배열을 사용하여 문자열을 다루는 것이 일반적인 방법입니다.

#include <stdio.h>

int main() {
    char name[] = "Hello, World!";  // 문자열 저장
    printf("문자열: %s\n", name);  // 문자열 출력
    return 0;
}

namechar 배열로, 문자열 "Hello, World!"를 저장하고 있습니다. %sprintf에서 문자열을 출력할 때 사용되는 서식 지정자입니다.

부호 있는/없는 정수형


C 언어에서는 정수형 데이터 타입에 대해 부호가 있는(Signed)과 부호가 없는(Unsigned) 두 가지 방식이 있습니다. 부호 있는 정수형은 양수와 음수를 모두 처리할 수 있지만, 부호 없는 정수형은 오직 양수와 0만 처리할 수 있습니다. 이를 통해 개발자는 데이터가 음수를 가질 필요가 없을 때 더 효율적으로 메모리를 사용할 수 있습니다.

signed와 unsigned의 차이점

  • signed: 부호가 있는 정수형으로, 음수와 양수를 모두 저장할 수 있습니다. 기본적으로 intsigned int와 동일하게 취급됩니다.
  • unsigned: 부호가 없는 정수형으로, 음수 값을 저장할 수 없으며 오직 0 이상의 값만 저장할 수 있습니다. unsignedint보다 더 넓은 양수 범위를 제공합니다.

signed 예시


부호 있는 정수형은 양수와 음수를 모두 처리할 수 있습니다. 예를 들어, signed int는 -2,147,483,648에서 2,147,483,647까지의 값을 저장할 수 있습니다. 기본적으로 int는 부호 있는 정수형으로 간주됩니다.

#include <stdio.h>

int main() {
    signed int a = -10;
    signed int b = 20;

    printf("a: %d\n", a);  // 출력: -10
    printf("b: %d\n", b);  // 출력: 20

    return 0;
}

위 예시에서 signed int는 음수와 양수 모두를 처리할 수 있습니다.

unsigned 예시


unsigned는 부호가 없는 정수형으로, 음수 값을 저장할 수 없으며, 0 이상의 값만 처리합니다. unsigned int는 보통 0에서 4,294,967,295까지의 값을 저장할 수 있습니다. 음수 값을 저장하려고 하면 잘못된 결과가 발생할 수 있으므로 주의해야 합니다.

#include <stdio.h>

int main() {
    unsigned int a = 10;
    unsigned int b = 20;

    printf("a: %u\n", a);  // 출력: 10
    printf("b: %u\n", b);  // 출력: 20

    return 0;
}

위 코드는 unsigned int 변수를 사용하여 양수 값을 출력합니다. %uunsigned int 값을 출력하는 서식 지정자입니다.

부호 있는/없는 정수형의 사용 이유

  • 부호 있는 정수형 (signed): 양수와 음수 모두를 처리해야 하는 경우 사용됩니다. 예를 들어, 온도나 금액과 같이 음수와 양수 값이 모두 필요한 상황에서 사용합니다.
  • 부호 없는 정수형 (unsigned): 값이 항상 양수이거나 0인 경우 사용됩니다. 예를 들어, 메모리 크기, 배열의 인덱스, 파일 크기 등은 항상 음수 값을 가질 수 없기 때문에 unsigned가 적합합니다.

부호 있는/없는 정수형의 메모리 범위 비교

데이터 타입크기값의 범위예시 값
signed int4바이트-2,147,483,648 ~ 2,147,483,647-100, 42
unsigned int4바이트0 ~ 4,294,967,295100, 4294967295
signed short2바이트-32,768 ~ 32,767-1000, 2000
unsigned short2바이트0 ~ 65,5351000, 65535

위 표는 signedunsigned 정수형의 크기와 값의 범위를 비교한 것입니다. unsigned는 음수를 다루지 않지만, 동일한 크기에서 더 넓은 양수 범위를 제공합니다.

포인터와 관련된 데이터 타입


C 언어에서 포인터는 변수의 메모리 주소를 저장하는 특별한 데이터 타입입니다. 포인터를 사용하면 변수의 값을 직접 수정하거나 함수에서 인수로 전달된 변수에 접근할 수 있습니다. 포인터는 C 언어에서 매우 중요한 개념으로, 특히 동적 메모리 할당, 배열, 함수 간 데이터 전달 등을 효율적으로 처리할 수 있도록 돕습니다.

포인터의 기본 개념


포인터는 다른 변수의 메모리 주소를 저장하는 변수입니다. 포인터를 선언할 때는 * 기호를 사용합니다. 예를 들어, int *ptr;ptrint형 데이터를 가리키는 포인터임을 의미합니다. 포인터는 변수의 실제 값을 저장하는 것이 아니라, 해당 변수의 메모리 주소를 저장합니다.

#include <stdio.h>

int main() {
    int a = 10;
    int *ptr = &a;  // ptr은 a의 주소를 가리킴

    printf("a의 값: %d\n", a);     // 출력: 10
    printf("ptr이 가리키는 값: %d\n", *ptr);  // 출력: 10 (ptr이 가리키는 주소의 값)
    return 0;
}

위 코드에서 &a는 변수 a의 메모리 주소를 반환하며, *ptrptr이 가리키는 주소에 저장된 값을 가져옵니다. ptra의 주소를 저장하고 있으며, 이를 통해 a의 값을 간접적으로 다룰 수 있습니다.

포인터 연산


포인터는 메모리 주소를 다루기 때문에 주소 연산이 가능합니다. 예를 들어, 포인터를 사용하여 배열의 요소를 순차적으로 접근하거나, 동적 메모리 할당에서 메모리 주소를 조작할 수 있습니다. 포인터 연산에는 ++, -- 같은 증감 연산자를 사용하여 메모리 주소를 변경할 수 있습니다.

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40};
    int *ptr = arr;  // 배열의 첫 번째 요소의 주소를 가리킴

    // 포인터를 이용해 배열의 요소 출력
    for (int i = 0; i < 4; i++) {
        printf("arr[%d] = %d\n", i, *ptr);
        ptr++;  // 포인터가 다음 배열 요소를 가리키도록 이동
    }
    return 0;
}

위 코드에서는 ptr++을 사용하여 배열의 각 요소에 접근하고 있습니다. 포인터는 메모리 주소를 직접 조작하므로, 배열 요소나 연속된 데이터를 처리하는 데 유용합니다.

포인터와 배열


C 언어에서 배열은 실제로 포인터와 밀접한 관계가 있습니다. 배열 이름은 배열의 첫 번째 요소의 주소를 나타내므로, 배열을 포인터처럼 사용할 수 있습니다. 배열의 각 요소에 접근하는 방법은 두 가지가 있습니다. 하나는 배열 인덱스를 사용하는 방법이고, 다른 하나는 포인터를 사용하는 방법입니다.

#include <stdio.h>

int main() {
    int arr[] = {10, 20, 30, 40};
    int *ptr = arr;

    // 배열을 포인터로 접근
    printf("arr[0] = %d\n", *(ptr));   // 출력: 10
    printf("arr[1] = %d\n", *(ptr + 1));  // 출력: 20

    return 0;
}

위 코드에서는 ptr을 포인터로 사용하여 배열 요소를 출력하고 있습니다. *(ptr + 1)은 배열의 두 번째 요소를 가리키는 방법입니다.

포인터와 동적 메모리 할당


포인터는 동적 메모리 할당과 함께 자주 사용됩니다. malloc(), calloc(), free() 함수는 C 표준 라이브러리에서 제공하는 동적 메모리 할당 관련 함수입니다. malloc()은 지정된 크기의 메모리를 할당하고 그 메모리의 시작 주소를 반환합니다. 이 주소는 포인터 변수에 저장하여 메모리를 관리합니다.

#include <stdio.h>
#include <stdlib.h>

int main() {
    int *ptr;

    // 동적 메모리 할당
    ptr = (int *)malloc(4 * sizeof(int));  // 4개의 int 크기만큼 메모리 할당

    if (ptr == NULL) {
        printf("메모리 할당 실패\n");
        return 1;
    }

    // 메모리 할당 후 사용
    for (int i = 0; i < 4; i++) {
        ptr[i] = (i + 1) * 10;
    }

    // 할당된 메모리 출력
    for (int i = 0; i < 4; i++) {
        printf("ptr[%d] = %d\n", i, ptr[i]);
    }

    // 동적 메모리 해제
    free(ptr);

    return 0;
}

이 코드에서 malloc()을 사용하여 4개의 int 크기만큼 동적 메모리를 할당하고, 할당된 메모리 주소를 ptr 포인터에 저장하여 데이터를 처리한 후, free()를 사용하여 메모리를 해제합니다.

포인터와 함수


포인터는 함수 간 데이터 전달에 유용하게 사용됩니다. 기본적으로 C에서는 함수 인수로 값이 전달되지만, 포인터를 사용하면 변수의 메모리 주소를 전달하여 함수 내에서 변수 값을 직접 수정할 수 있습니다. 이를 통해 메모리 복사를 피하고 성능을 최적화할 수 있습니다.

#include <stdio.h>

void modifyValue(int *ptr) {
    *ptr = 100;  // 포인터를 통해 전달된 변수의 값을 수정
}

int main() {
    int a = 10;
    printf("a의 값 (수정 전): %d\n", a);

    modifyValue(&a);  // a의 주소를 전달

    printf("a의 값 (수정 후): %d\n", a);  // 출력: 100
    return 0;
}

위 코드에서 modifyValue 함수는 a의 주소를 인수로 받아 그 값을 직접 수정합니다. 포인터를 통해 함수 외부의 변수 값을 변경할 수 있기 때문에 매우 유용한 기능입니다.

구조체와 공용체


C 언어에서 구조체(struct)와 공용체(union)는 여러 개의 변수들을 하나의 단위로 묶을 수 있는 데이터 타입입니다. 두 가지는 비슷하게 여러 데이터를 한 번에 다룰 수 있지만, 메모리 관리 방식에서 차이가 있습니다. 이들 자료형은 복잡한 데이터를 효율적으로 다룰 수 있게 해줍니다.

구조체 (struct)


구조체는 여러 다른 타입의 데이터를 하나로 묶을 수 있는 데이터 타입입니다. 구조체 내에 포함된 각각의 변수는 멤버라고 불리며, 각 멤버는 독립적인 메모리 공간을 가집니다. 구조체를 사용하면 다양한 속성을 하나의 객체처럼 묶어서 처리할 수 있습니다.

구조체 선언과 사용


구조체는 struct 키워드를 사용하여 선언합니다. 선언된 구조체 타입을 기반으로 변수를 선언하여 사용할 수 있습니다.

#include <stdio.h>

// 구조체 선언
struct Person {
    char name[50];
    int age;
    float height;
};

int main() {
    // 구조체 변수 선언
    struct Person person1 = {"John Doe", 25, 5.9};

    // 구조체 멤버에 접근하여 출력
    printf("이름: %s\n", person1.name);
    printf("나이: %d\n", person1.age);
    printf("키: %.1f\n", person1.height);

    return 0;
}

이 예시에서 Person 구조체는 이름, 나이, 키를 멤버로 가지고 있습니다. 구조체 변수를 선언한 후, 각 멤버에 접근하여 값을 출력할 수 있습니다. 구조체의 멤버에 접근할 때는 . 연산자를 사용합니다.

구조체의 크기


구조체의 크기는 각 멤버의 크기를 모두 합친 값이지만, 컴파일러가 메모리 정렬을 최적화하기 위해 추가적인 패딩을 삽입할 수 있습니다. 따라서 구조체의 실제 크기는 멤버들의 크기의 합과는 다를 수 있습니다.

#include <stdio.h>

struct Example {
    char a;
    int b;
    char c;
};

int main() {
    struct Example ex;
    printf("구조체 크기: %lu\n", sizeof(ex));  // 예시 크기 출력
    return 0;
}

위 코드에서 char는 1바이트, int는 4바이트이지만, 구조체의 실제 크기는 12바이트일 수 있습니다. 이는 메모리 정렬을 맞추기 위해 charint 사이에 패딩이 추가되었기 때문입니다.

공용체 (union)


공용체는 구조체와 비슷하지만, 모든 멤버가 동일한 메모리 공간을 공유합니다. 즉, 공용체의 모든 멤버는 동일한 메모리 주소를 사용하며, 한 번에 하나의 멤버만 사용할 수 있습니다. 공용체를 사용할 때, 가장 큰 멤버의 크기만큼 메모리를 할당받습니다.

공용체 선언과 사용


공용체는 union 키워드를 사용하여 선언합니다. 구조체와 달리, 공용체의 멤버들은 서로 겹치는 메모리 공간을 사용하므로, 한 번에 하나의 멤버만 값을 가질 수 있습니다.

#include <stdio.h>

// 공용체 선언
union Data {
    int i;
    float f;
    char str[20];
};

int main() {
    union Data data;

    data.i = 10;  // int형 변수에 값 할당
    printf("i: %d\n", data.i);

    data.f = 220.5;  // float형 변수에 값 할당 (이전 값은 덮어씀)
    printf("f: %.2f\n", data.f);

    // 문자열에 값 할당
    snprintf(data.str, sizeof(data.str), "Hello, Union!");
    printf("str: %s\n", data.str);

    return 0;
}

위 예시에서 공용체 Dataint, float, char[] 세 가지 멤버를 가지고 있습니다. 공용체의 멤버는 같은 메모리 공간을 공유하므로, i, f, str에 각각 값을 저장할 때 마지막에 저장한 값만 유효합니다. 첫 번째 값은 덮어쓰여지게 됩니다.

구조체와 공용체의 차이점

특성구조체 (struct)공용체 (union)
메모리 할당 방식각 멤버마다 독립적인 메모리 할당모든 멤버가 동일한 메모리 공간을 공유
크기모든 멤버의 크기 합산가장 큰 멤버의 크기만큼 할당
멤버의 값모든 멤버가 동시에 값 가짐한 번에 하나의 멤버만 값 가짐
사용 예다양한 데이터를 동시에 저장메모리를 절약하며, 한 가지 데이터만 저장

구조체와 공용체의 사용 사례

  • 구조체: 다양한 종류의 데이터가 함께 묶여야 할 때 유용합니다. 예를 들어, 학생의 정보를 저장하는 구조체는 이름, 학번, 성적 등 서로 다른 유형의 데이터를 하나로 묶어서 다룰 수 있습니다.
  • 공용체: 메모리 효율성을 중시할 때 유용합니다. 예를 들어, 다양한 형식의 데이터를 하나의 공간에서 다뤄야 할 때 공용체를 사용할 수 있습니다. 하지만, 동시에 하나의 데이터만 사용하므로 적절한 상황에서만 사용해야 합니다.

열거형 (enum) 데이터 타입


C 언어에서 열거형(enum)은 변수에 대해 미리 정의된 상수 값을 할당할 수 있는 데이터 타입입니다. 열거형을 사용하면 코드의 가독성을 높이고, 상수 값을 숫자로 표현하는 대신 의미 있는 이름을 사용할 수 있습니다. 이를 통해 코드에서 특정 값이 무엇을 의미하는지 직관적으로 알 수 있습니다.

열거형 기본 개념


열거형은 enum 키워드를 사용하여 정의합니다. 각 항목은 기본적으로 0부터 시작하는 정수 값을 가지며, 그 이후 항목들은 이전 항목의 값에 1을 더한 값을 가집니다. 만약 값을 명시적으로 지정하면, 나머지 항목들은 그에 따라 값을 증가시켜 할당합니다.

열거형 선언과 사용

#include <stdio.h>

// 열거형 정의
enum Weekday {
    Sunday,    // 0
    Monday,    // 1
    Tuesday,   // 2
    Wednesday, // 3
    Thursday,  // 4
    Friday,    // 5
    Saturday   // 6
};

int main() {
    enum Weekday today = Wednesday;  // 변수에 열거형 값 할당

    printf("오늘은 %d 번째 요일입니다.\n", today);  // 출력: 오늘은 3 번째 요일입니다.

    return 0;
}

위 코드에서 enum Weekday는 일주일의 요일을 나타내는 열거형입니다. Sunday부터 Saturday까지 각 항목은 기본적으로 0에서 6까지의 값을 가집니다. 변수 todayWednesday로 초기화되며, 이는 3으로 출력됩니다.

열거형 값 지정하기


열거형 항목에 값을 명시적으로 지정할 수 있습니다. 이 경우, 첫 번째 항목에 값을 지정하면, 이후 항목들은 자동으로 그 값을 기준으로 증가하거나 감소합니다.

#include <stdio.h>

// 열거형 값 명시적 지정
enum Weekday {
    Sunday = 1,  // 1
    Monday = 5,  // 5
    Tuesday,     // 6
    Wednesday,   // 7
    Thursday,    // 8
    Friday,      // 9
    Saturday     // 10
};

int main() {
    enum Weekday today = Tuesday;  // 변수에 열거형 값 할당

    printf("오늘은 %d 번째 요일입니다.\n", today);  // 출력: 오늘은 6 번째 요일입니다.

    return 0;
}

위 코드에서는 Sunday1을 할당하고, 그 이후 항목들은 자동으로 1씩 증가합니다. 따라서 Monday5, Tuesday6이 됩니다.

열거형의 크기


C 언어에서 열거형의 크기는 int 타입에 의존하며, 시스템에 따라 다를 수 있습니다. 기본적으로 열거형은 int로 처리되므로 int 타입과 동일한 크기를 가집니다.

#include <stdio.h>

enum Weekday {
    Sunday = 1,  // 1
    Monday,      // 2
    Tuesday,     // 3
    Wednesday,   // 4
    Thursday,    // 5
    Friday,      // 6
    Saturday     // 7
};

int main() {
    enum Weekday today = Wednesday;
    printf("열거형 크기: %lu 바이트\n", sizeof(today));  // 출력: 열거형 크기: 4 바이트

    return 0;
}

이 예시에서 열거형 Weekday의 크기를 출력하면, 대부분의 시스템에서 int의 크기인 4바이트가 출력됩니다.

열거형과 문자열


열거형 항목은 숫자로 표현되지만, 이를 사람이 읽을 수 있는 문자열로 변환하는 방법은 switch 문이나 별도의 함수를 사용하여 구현할 수 있습니다. C 언어는 기본적으로 열거형 값을 문자열로 변환하는 기능을 제공하지 않기 때문에 이를 수동으로 구현해야 합니다.

#include <stdio.h>

enum Weekday {
    Sunday = 1,
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday
};

// 열거형 값을 문자열로 변환하는 함수
const char* getDayName(enum Weekday day) {
    switch (day) {
        case Sunday: return "Sunday";
        case Monday: return "Monday";
        case Tuesday: return "Tuesday";
        case Wednesday: return "Wednesday";
        case Thursday: return "Thursday";
        case Friday: return "Friday";
        case Saturday: return "Saturday";
        default: return "Invalid Day";
    }
}

int main() {
    enum Weekday today = Friday;
    printf("오늘은 %s 입니다.\n", getDayName(today));  // 출력: 오늘은 Friday 입니다.

    return 0;
}

이 코드에서는 getDayName 함수를 사용하여 열거형 값을 해당하는 문자열로 변환하고 있습니다. switch 문을 활용하여 열거형 값에 맞는 문자열을 반환합니다.

열거형 사용의 장점

  1. 코드 가독성 향상: 열거형을 사용하면 숫자 대신 의미 있는 이름을 사용할 수 있기 때문에 코드가 훨씬 읽기 쉬워집니다.
  2. 유지보수 용이성: 열거형에 정의된 값은 모두 하나의 타입에 묶여 있으므로, 코드 변경 시 안전하게 관리할 수 있습니다.
  3. 오류 예방: 열거형을 사용함으로써 프로그램에서 사용 가능한 값이 제한되므로, 잘못된 값이 할당되는 실수를 줄일 수 있습니다.

열거형의 실용적인 사용 예

  • 상태 값 관리: 프로그램 내에서 특정 상태를 나타내는 값들을 열거형으로 정의하여 코드의 의미를 명확히 할 수 있습니다. 예를 들어, 게임의 상태(시작, 진행 중, 종료 등)를 나타내는 데 유용합니다.
  • 플래그 값 관리: 여러 가지 옵션을 선택해야 하는 경우, 비트 마스크와 함께 열거형을 사용할 수 있습니다. 예를 들어, 파일 권한(읽기, 쓰기, 실행)을 관리하는 데 유용합니다.
목차