Skip to main content

Command Palette

Search for a command to run...

Variables, constants, and data types in C (1/2)

변수와 상수 자료형, 자료형 표현 방법 C언어

Updated
18 min read
Variables, constants, and data types in C (1/2)

Contents

1️⃣ 변수와 상수의 개념 이해 (Concept of variable and constants)
2️⃣ 자료형과 정수형 자료형(Datatype and interger data type)
3️⃣ 오버플로우 (Overflow)
4️⃣ 상수의 자료형을 명시적으로 지정하기 (Explicitly specifying the data type of a constant)


1️⃣ 변수와 상수의 개념 이해

(Concept of variable and constants)

변수란? (What is Variables?)

변수는 프로그램에서 데이터를 효율적으로 관리하고 참조하는 데 중요한 역할을 한다.

컴퓨터 프로그램은 값(데이터)을 저장하기 위하여 변수(variable)을 사용한다.

변수는 게임에서 점수를 저장하는데 사용될 수 있고, 대형 마트에서 우리가 구입한 물건들의 가격을 저장할 수도 있다.

저장하는 데이터의 종류는 여러가지가 있는데 이 데이터를 이용할 수 있도록 제공해주는 곳이 “변수”이다.


변수의 역할(Role of Variable)

  • 데이터 저장(Store data): 사용자가 입력한 데이터를 메모리에 저장한다.

  • 데이터 처리(Process data): 저장된 변수 값을 사용하여 계산, 비교, 출력 등 다양한 작업을 수행한다.


변수는 어디에 만들어지는가? (Where Variable made?)

사용자가 코드를 통해 변수에 값을 할당하면, 컴퓨터는 이 값을 메인 메모리(RAM)에 저장하게 되는데 이 공간에는 각 변수마다 고유의 주소(address)가 할당된다. 변수 이름을 통해 이 주소를 참조하여 메모리 위치에 접근할 수 있게 된다. 이를 통해 값을 읽거나 수정할 수 있게된다.


변수란 왜 필요한가? #1 (Why Variable is needed?)

변수가 없다면:

  • 데이터를 저장할 메모리 공간을 확보할 수 없기 때문에, 사용자로부터 받은 데이터를 프로그램 내에서 유지하거나 처리할 수 없습니다.

  • 예를 들어, 사용자가 입력한 여러 숫자(성적, 가격 등)를 변수 없이 관리하려면, 각 데이터를 매번 새롭게 입력받거나 외부 저장소를 사용해야 하므로 프로그램의 효율성이 떨어집니다.

따라서 변수는 프로그램 내에서 데이터를 저장하고 처리할 수 있도록 메모리에 특정 공간을 할당하고, 이를 효율적으로 활용하게 해주는 매우 중요한 요소입니다.


변수란 왜 필요한가? #2 (Why Variable is needed?)

💡요약: 변수는 코드의 가독성, 유지보수성, 재사용성을 높여주는 중요한 요소이다. 이를 통해 코드의 의미를 명확히 하고, 더 쉽게 관리할 수 있는 구조를 만들어준다.

변수를 사용하는 코드와 변수를 사용하지 않는 코드를 비교해보자.

변수를 사용하지 않은 코드(Code without Variables)

// 크기가 100x200인 사각형의 면적
area = 100 * 200;

위 코드는 100과 200이 어떤 값인지, 어떤 의미를 가지는지 알기 어렵다.

변수를 사용하는 코드(Code with Variables)

// 크기가 width x height인 사각형의 면적
width = 100;
height = 200;
area = width * height;

위 코드는 widthheight라는 변수를 사용하여 사각형의 크기를 지정하고, 면적을 계산할 때 해당 변수를 사용하고 있다. 이처럼 변수를 사용하면 코드의 의미가 더 명확해지고, 유지보수와 확장성이 좋아진다.

변수 사용의 장점(Advantage of variable)

  1. 가독성(Readability)

    • 변수를 사용하지 않는 코드(area = 100 * 200;)는 단순히 숫자만 나열되어 있어서, 나중에 코드를 볼 때 100과 200이 무엇을 의미하는지 이해하기 어려울 수 있다.

    • 반면에 변수를 사용한 코드(width = 100; height = 200; area = width * height;)는 widthheight라는 변수명을 통해 코드의 의미를 쉽게 파악할 수 있다.

  2. 유지보수 용이성(Easy maintenance)

    • 변수를 사용하지 않은 코드에서는 값을 변경할 때마다 모든 관련 부분을 수정해야 하는 번거로움이 있다.

    • 변수를 사용한 코드에서는 값만 수정하면 이를 참조하는 모든 곳에서 자동으로 반영된다. 예를 들어, widthheight 변수를 변경하면 area 값도 자동으로 갱신된다.

  3. 재사용성(Reuasable)

    • 변수를 사용하면 같은 변수명을 사용하여 다양한 연산과 기능에 재사용할 수 있어, 코드의 효율성을 높일 수 있다.

변수와 상수(Variable and constant)

변수와 상수는 프로그램에서 데이터를 저장할 때 사용하는 중요한 요소이다. 두 개념의 차이점을 이해하고, 적절하게 활용하면 프로그램의 안정성과 가독성을 높일 수 있수 있게된다.

변수 (Variable)

  • 정의: 변수는 값이 변경될 수 있는 메모리 공간이다.

  • 특징: 프로그램 실행 도중 변수에 저장된 값을 변경할 수 있다.

  • 예시:

      # 변수 사용 예시
      score = 50       # 초기값 50 할당
      score = 100      # 값 변경 (50 → 100)
      print(score)     # 출력: 100
    

    위 예제에서 score라는 변수는 50에서 100으로 값이 변경될 수 있는 공간이다.

상수 (Constant)

  • 정의: 상수는 값이 한 번 저장되면 변경할 수 없는 메모리 공간이다.

  • 특징: 프로그램 실행 도중 값이 변하지 않으므로, 값이 고정된 데이터를 표현할 때 사용한다.

  • 예시:

      # 상수 사용 예시 (파이썬에서는 상수를 별도로 지원하지 않지만, 변수명을 대문자로 사용하여 관례적으로 표현)
      PI = 3.14        # 원주율 상수
      print(PI)        # 출력: 3.14
    
      # PI = 3.14159   # 상수 값을 변경하면 안 됨 (실제 사용 시 값 변경을 피해야 함)
    

    위 예제에서 PI는 원주율을 나타내는 상수로, 프로그램 내에서 값을 변경하지 않도록 사용한다.

변수와 상수의 차이점

구분변수상수
값 변경변경 가능변경 불가능
용도자주 바뀌는 데이터 (예: 점수, 사용자의 나이 등)고정된 데이터 (예: 원주율, 중력 가속도 등)
표기법소문자 또는 카멜케이스 (예: userName, score)대문자 (예: PI, MAX_VALUE)

상수의 장점(Pros of constant)

  • 코드 안정성(Code stability): 프로그램이 실행되는 동안 값이 변경되지 않으므로, 예기치 않은 오류를 방지할 수 있다.

  • 가독성(Readability): 의미가 명확한 이름을 사용해 상수를 정의하면 코드의 가독성을 높일 수 있다.

  • 유지보수성(Easy maintainance): 특정 값(예: 원주율, 세율 등)이 코드 여러 곳에서 사용될 때, 상수로 정의해두면 한 곳에서만 변경하면 되므로 유지보수가 쉽다.

예제: 변수와 상수 (Example of variable and constants)

코드 분석

#include <stdio.h>  // 표준 입출력 라이브러리 포함

int main(void)
{
    float radius;   // 반지름을 저장하는 변수
    float area;     // 원의 면적을 저장하는 변수

    printf("원의 반지름을 입력하세요.");  // 사용자로부터 반지름을 입력받음
    scanf("%f", &radius);               // 반지름 값을 변수 radius에 저장

    area = 3.141592 * radius * radius;   // 상수 3.141592 (원주율)을 사용하여 면적 계산
    printf("원의 면적: %f\n", area);     // 계산된 면적 출력

    return 0;                           // 프로그램 종료
}

주요 요소

  1. 변수 (radius, area)

    • radius: 사용자로부터 입력받은 원의 반지름을 저장하는 변수.

    • area: 원의 면적을 저장하는 변수.

이 두 변수는 사용자가 입력한 값과 계산된 값을 저장할 수 있으며, 프로그램 실행 도중 여러 번 값이 변경될 수 있다.

  1. 상수 (3.141592)

    • 3.141592는 원의 면적을 계산할 때 사용되는 원주율로, 값이 변경되지 않는 상수입니다.

    • 원주율을 코드 내에서 직접 사용하지 않고 상수로 정의하는 것이 일반적이다. 상수를 사용하면 원주율 값이 변경될 일이 있을 때, 코드 전체를 수정할 필요 없이 상수 값만 변경하면 된다.

개선된 상수 사용 예시

위 코드는 상수를 직접 숫자로 표현했지만, #define을 사용하여 상수를 정의할 수도 있다.

#include <stdio.h>

#define PI 3.141592  // 상수 정의

int main(void)
{
    float radius;
    float area;

    printf("원의 반지름을 입력하세요: ");
    scanf("%f", &radius);

    area = PI * radius * radius;  // 상수 PI를 사용하여 원의 면적 계산
    printf("원의 면적: %f\n", area);

    return 0;
}

위 코드에서는 #define PI 3.141592를 사용하여 상수를 정의했기 때문에, PI 값을 수정할 일이 생기더라도 한 번만 수정하면 된다. 상수를 사용할 때에는 코드의 의미를 더 명확하게 표현할 수 있게된다.

이처럼 변수와 상수를 적절히 사용하여 프로그램의 명확성과 안정성을 높일 수 있다.


2️⃣ 자료형과 정수형 자료형(Datatype and interger data type)

자료형

자료형(Data Type)은 프로그래밍에서 데이터의 종류를 정의하는 중요한 개념이다. 각 자료형은 메모리에서 데이터를 저장하는 방식과 크기가 다르며, 데이터에 따라 어떤 연산을 할 수 있는지 결정한다.

자료형의 종류

자료형은 크게 정수형(integer), 부동소수점형(floating point), 문자형(character) 등으로 나눌 수 있다.

  1. 정수형 자료형(integer): 정수형 자료형은 소수점이 없는 정수 데이터를 저장한다.

    • short: 메모리를 적게 사용하며, -32,768에서 32,767 사이의 정수를 저장할 수 있다.

    • int: 일반적으로 사용되는 정수형으로, -2,147,483,648에서 2,147,483,647까지의 정수를 저장할 수 있다.

    • long: 더 큰 범위의 정수를 저장할 수 있으며, 메모리도 더 많이 사용한다.

예시:

    num1 = 100;    // short형 변수
    int num2 = 1000;     // int형 변수
    long num3 = 100000;  // long형 변수
  1. 부동소수점형 자료형(Floating point): 실수 데이터를 저장하며, 정밀한 소수점을 표현할 수 있다.

    • float: 단정도 실수형으로 소수점 이하 6~7자리 정도의 정밀도를 가진다.

    • double: 배정도 실수형으로 소수점 이하 15~16자리 정도의 정밀도를 가진다. float보다 더 많은 메모리를 사용하며, 더 정밀한 실수 데이터를 표현할 수 있다.

예시:

    num1 = 3.14f;      // float형 변수 (f를 붙여야 함)
    double num2 = 3.141592;  // double형 변수
  1. 문자형 자료형(character): 하나의 문자 데이터를 저장한다.

    • char: 1바이트(= 8 비트) 크기의 문자형 자료형으로, 하나의 문자('A', 'B', '1', '한' 등)를 저장할 수 있다.

예시:

    letter = 'A';    // char형 변수에 문자 'A' 저장
    char korean = '한';    // char형 변수에 문자 '한' 저장

다양한 자료형이 필요한 이유

자료형을 선택하는 것은 상자에 물건을 담는 것과 같다. 너무 작은 상자는 물건을 담을 수 없고, 너무 큰 상자는 공간이 낭비된다. 프로그래밍에서도 데이터를 효율적으로 저장하기 위해 적절한 자료형을 선택하여 메모리 낭비를 줄이고 프로그램의 성능을 최적화할 수 있다.

비유 설명

  1. 물건이 상자보다 큰 경우:

    • 설명: 만약 물건이 상자보다 크면, 상자 안에 물건을 넣을 수 없게 된다.

    • 프로그래밍 비유: 예를 들어, short 자료형의 변수에 매우 큰 수(예: 1,000,000)를 저장하려고 하면, 자료형의 크기를 초과하여 값이 제대로 저장되지 않거나 오류가 발생할 수 있다.

  2. 물건이 상자보다 작은 경우:

    • 설명: 물건이 상자보다 지나치게 작으면, 상자 안에 공간이 많이 남아 비효율적이다.

    • 프로그래밍 비유: 예를 들어, 단순한 정수(1, 2, 3)를 저장하려고 하는데 long 자료형(8바이트)을 사용하면, 불필요하게 큰 메모리 공간이 할당되어 메모리 낭비가 발생하게 된다.


자료형의 분류

자료형은 크게 정수형(integer), 부동소수점형(floating point), 문자형(character)으로 분류할 수 있다. 각 자료형은 특정 범위의 값을 저장할 수 있고, 고유의 특성과 용도를 가지고 있다.

자료형의 크기

자료형의 크기를 알아보려면 sizeof 연산자를 사용하면 된다. sizeof는 변수나 자료형의 크기 를 바이트 단위로 반환하는 연산자로 메모리 관리와 최적화에 유용한 도구이다.

sizeof 연산자는 C, C++, Python 등의 언어에서 변수나 자료형의 크기를 알아볼 때 사용하는 연산자이다. 이 연산자는 해당 변수 또는 자료형이 메모리에서 차지하는 크기바이트(byte) 단위로 반환한다. sizeof를 사용하면 각 자료형의 메모리 크기를 명확하게 알 수 있어, 메모리 관리나 최적화 작업 시 유용하다.

sizeof 연산자 사용 방법

  1. 변수의 크기 확인: 특정 변수가 메모리에서 얼마나 많은 공간을 차지하는지 확인할 수 있다.

     int number;
     printf("number 변수의 크기: %zu 바이트\n", sizeof(number));  // 출력: 4 바이트
    
  2. 자료형의 크기 확인: 특정 자료형이 메모리에서 얼마나 많은 공간을 차지하는지 확인할 수 있다.

     printf("int 자료형의 크기: %zu 바이트\n", sizeof(int));  // 출력: 4 바이트
     printf("double 자료형의 크기: %zu 바이트\n", sizeof(double));  // 출력: 8 바이트
    
  3. 배열이나 구조체의 크기 확인: 배열이나 사용자 정의 구조체의 크기도 확인할 수 있다.

     int arr[10];
     printf("배열 arr의 크기: %zu 바이트\n", sizeof(arr));  // 출력: 40 바이트 (int형이 4바이트이므로 4 x 10)
    

자료형의 예제 코드 (Code example of Data type)

아래는 다양한 자료형의 크기를 sizeof 연산자를 사용하여 출력하는 예제이다.

#include <stdio.h>

int main() {
    // 다양한 자료형 선언
    char ch;
    short sh;
    int in;
    long lo;
    float fl;
    double db;

    // 각 자료형의 크기 출력
    printf("char 자료형의 크기: %zu 바이트\n", sizeof(char));
    printf("short 자료형의 크기: %zu 바이트\n", sizeof(short));
    printf("int 자료형의 크기: %zu 바이트\n", sizeof(int));
    printf("long 자료형의 크기: %zu 바이트\n", sizeof(long));
    printf("float 자료형의 크기: %zu 바이트\n", sizeof(float));
    printf("double 자료형의 크기: %zu 바이트\n", sizeof(double));

    // 변수의 크기 출력
    printf("변수 ch의 크기: %zu 바이트\n", sizeof(ch));
    printf("변수 sh의 크기: %zu 바이트\n", sizeof(sh));
    printf("변수 in의 크기: %zu 바이트\n", sizeof(in));
    printf("변수 lo의 크기: %zu 바이트\n", sizeof(lo));
    printf("변수 fl의 크기: %zu 바이트\n", sizeof(fl));
    printf("변수 db의 크기: %zu 바이트\n", sizeof(db));

    return 0;
}

예제 출력 (시스템에 따라 다를 수 있음)

char 자료형의 크기: 1 바이트
short 자료형의 크기: 2 바이트
int 자료형의 크기: 4 바이트
long 자료형의 크기: 8 바이트
float 자료형의 크기: 4 바이트
double 자료형의 크기: 8 바이트
변수 ch의 크기: 1 바이트
변수 sh의 크기: 2 바이트
변수 in의 크기: 4 바이트
변수 lo의 크기: 8 바이트
변수 fl의 크기: 4 바이트
변수 db의 크기: 8 바이트

정수형(Interger)

이미지에서 자료형의 크기를 상자로 비유하여 설명하고 있다:

  • short 상자는 가장 작으며, 16비트(2바이트)만큼의 크기이다.

  • int 상자는 short 상자보다 크고, 32비트(4바이트)만큼의 크기이다.

  • long 상자 역시 32비트(4바이트)의 크기를 가진다.

  • long long 상자는 가장 큰 상자로, 64비트(8바이트)의 크기를 나타낸다.

이 비유를 통해 다음과 같은 사실을 이해할 수 있다.

  • 작은 상자에는 작은 값만 저장할 수 있지만, 큰 상자에는 작은 값과 큰 값 모두 저장할 수 있다.

  • 큰 상자를 사용할수록 메모리 낭비가 발생할 수 있으므로, 데이터의 크기에 맞는 자료형을 사용하는 것이 중요하다.


정수형 자료형의 크기와 범위(The size and range of interger data type)

정수형 자료형은 기본적으로 short, int, long, long long 네 가지로 나뉘며, 각 자료형이 차지하는 비트 크기저장 가능한 값의 범위는 다음과 같다.

자료형비트 크기저장할 수 있는 값의 범위
short16비트 (2바이트)-32,768 ~ 32,767
int32비트 (4바이트)-2,147,483,648 ~ 2,147,483,647
long32비트 (4바이트)-2,147,483,648 ~ 2,147,483,647
long long64비트 (8바이트)-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807

각 자료형의 크기와 비교

short는 16비트(2바이트)로, 가장 작은 크기의 정수형 자료형이다.

  • intlong은 일반적으로 32비트(4바이트)를 차지하며, 정수형 자료형의 기본 크기로 사용된다. 일부 시스템에서는 long 자료형이 64비트를 차지할 수도 있다.

  • long long은 64비트(8바이트)로 가장 큰 크기의 정수형 자료형이다. 큰 수를 표현할 때 사용된다.

정수형 자료형 선택의 기준

  1. short: 작은 범위의 정수 값을 저장할 때 사용한다. 예를 들어, 학생의 나이, 학년 등.

  2. int: 일반적으로 정수형 변수를 선언할 때 기본으로 사용된다. int는 대부분의 연산에서 성능과 메모리 측면에서 적절한 균형을 제공한다.

  3. long: int와 같은 크기이지만, 일부 시스템에서는 더 큰 범위의 정수를 저장할 수 있도록 long이 64비트로 설정될 수 있다.

  4. long long: 아주 큰 정수 값이 필요한 경우 사용한다. 예를 들어, 큰 숫자 연산이나 대용량 데이터 처리가 필요한 경우.


C에서는 왜 이렇게 많은 종류의 정수형이 있을까?

  • C 언어에서 다양한 정수형 자료형이 존재하는 이유는 프로그램의 효율성과 메모리 사용을 최적화하기 위해서이다.

  • 비트 수가 늘어나면 표현할 수 있는 정수의 범위는 커지지만, 메모리 사용량도 증가한다.

  • 프로그래머는 프로그램의 목적과 저장할 데이터의 크기를 고려하여 가장 적절한 자료형을 선택함으로써, 메모리와 성능 측면에서 최적화된 프로그램을 작성할 수 있게 된다.

따라서, C 언어의 정수형 자료형은 프로그램의 성능과 효율성을 극대화할 수 있도록 다양한 선택지를 제공하는 중요한 요소가 된다.


정수형의 범위(Range of Interger)

각 정수형 자료형은 표현할 수 있는 값의 범위가 다르며, 이를 통해 프로그래머가 메모리 효율성이나 데이터 범위를 고려하여 적절한 자료형을 선택할 수 있도록 하였다.

  • int형 (32비트=4바이트)

    • 음수: -2^31 ~ -1 (최소 값: -2,147,483,648)

    • 양수: 0 ~ 2^31 - 1 (최대 값: 2,147,483,647)

    • 즉, int약 -21억에서 +21억까지의 범위를 표현할 수 있다.

  • short형 (16비트 = 2바이트)

    • 음수: -2^15 ~ -1 (최소 값: -32,768)

    • 양수: 0 ~ 2^15 - 1 (최대 값: 32,767)

    • 따라서, short약 -32,768에서 +32,767까지의 범위를 가진다.

  • long형 (32비트 or 64비트)

    • 만약 long이 64비트인 경우, 값의 범위는 다음과 같이 확장된다

    • 음수: -2^63 ~ -1 (최소 값: -9,223,372,036,854,775,808)

    • 양수: 0 ~ 2^63 - 1 (최대 값: 9,223,372,036,854,775,807)


예제


Signed, unsigned modifier (수식자)

위의 개념은 C 언어에서 정수형 변수가 표현할 수 있는 값의 범위를 결정하는 중요한 요소이다. signed와 unsigned 수식자는 정수형뿐만 아니라 문자형(char) 자료형에도 사용할 수 있다.

💡요약: signedunsigned 수식자는 정수형과 문자형 변수의 부호를 결정한다.

  • unsigned는 양수 값만 표현하고, signed는 음수와 양수를 모두 표현한다.

  • unsigned는 비트를 더 많이 활용하여 더 넓은 양수 범위를 표현할 수 있지만, 음수를 다룰 때는 사용할 수 없다.

  • 데이터를 정확하게 표현하기 위해서는 값의 범위를 고려하여 signedunsigned를 적절히 선택해야 한다.

signed와 unsigned의 차이

  1. unsigned (부호 없는 정수형)

    • 설명: unsigned음수 값을 표현하지 않고, 0과 양수만을 표현할 수 있는 자료형이다.

    • 용도: 양수만을 표현할 때, 값의 범위를 최대화하기 위해 사용한다.

    • 예시: unsigned int, unsigned char

    • 예시 값의 범위:

      • unsigned int: 0 ~ 4,294,967,295 (32비트일 때)

      • unsigned char: 0 ~ 255 (8비트일 때)

    • 특징:

      • 비트의 모든 자리를 값 표현에 사용할 수 있다.

      • 예를 들어, 8비트 unsigned char의 경우 모든 8비트를 사용하여 0~255 사이의 값을 표현할 수 있게한다.

  2. signed (부호 있는 정수형)

    • 설명: signed음수와 양수 모두를 표현할 수 있는 자료형이다. 부호를 표현하기 위해 가장 왼쪽 비트(부호 비트)를 사용한다.

    • 용도: 양수와 음수를 모두 사용할 때, 기본 정수형을 지정할 때 사용된다.

    • 예시: signed int, signed char

    • 예시 값의 범위:

      • signed int: -2,147,483,648 ~ 2,147,483,647 (32비트일 때)

      • signed char: -128 ~ 127 (8비트일 때)

    • 특징:

      • 가장 왼쪽의 1비트는 부호를 나타내는 데 사용되며, 나머지 비트로 값을 표현한다.

      • 예를 들어, 8비트 signed char의 경우 첫 번째 비트는 부호를 나타내고, 나머지 7비트는 숫자 값을 나타냅니다. 이를 통해 -128 ~ 127 범위의 값을 표현할 수 있게한다.

signed와 unsigned의 표현 방식

1. 부호 비트 (Sign Bit)

  • signed 자료형에서 가장 왼쪽의 1비트는 부호 비트로 사용된다

    • 0이면 양수, 1이면 음수를 의미한다.

    • 예를 들어, signed char형의 1000 0001은 -127을 의미하고, 0000 0001은 +1을 의미합니다.

2. 값의 범위 (사진참조)

  • unsigned양수 범위를 2배로 확장할 수 있지만, 음수 값은 표현할 수 없다.

    • 예를 들어, unsigned char는 0부터 42억까지 표현할 수 있지만, signed char는 -20억에서 +21억까지 표현할 수 있다.

unsigned와 signed의 선택 기준

  1. 양수만 사용할 때:

    • unsigned 자료형을 사용하는 것이 좋다.

    • 예: 물건의 수량, 점수, 나이 등 음수가 될 수 없는 값

  2. 양수와 음수를 모두 사용할 때:

    • signed 자료형을 사용하여 부호를 포함한 값을 표현할 수 있다.

    • 예: 온도(섭씨 -40도 ~ 100도), 은행 잔고(양수와 음수 모두 가능)

  3. char 자료형의 signed와 unsigned

    • char 자료형은 signed charunsigned char로 나눌 수 있다.

    • signed char는 -128에서 127까지, unsigned char는 0에서 255까지 표현할 수 있다.

    • char 자료형을 문자(예: 'A', 'B')로 사용할 때는 부호가 필요 없기 때문에 대부분 unsigned char를 사용한다.


Unsigned 예제


3️⃣ 오버플로우 (Overflow)

위 이미지에서는 오버플로우(Overflow)가 발생하는 상황을 예제 코드와 함께 설명하고 있다. short 자료형과 unsigned short 자료형의 최대값을 초과하는 값을 저장할 때 어떤 결과가 발생하는지 보여주고 있다.

💡요약: 오버플로우는 자료형의 최대값을 초과하는 값을 저장하려 할 때 발생하며, 예상치 못한 값이 저장되게 된다.

  • 부호가 있는 정수형(signed)에서는 최대값을 초과하면 가장 작은 음수 값으로, 부호가 없는 정수형(unsigned)에서는 0으로 순환된다.

  • 오버플로우를 방지하기 위해서는 더 큰 자료형을 사용하거나, 값의 범위를 확인하는 조건문을 추가하여 코드를 작성하는 것이 좋다.


오버플로우의 원인

  1. short 자료형 오버플로우:

    • s_money 변수는 short 자료형으로 선언되었으며, SHRT_MAXshort형의 최대값인 32,767로 초기화되었다.

    • s_money = s_money + 1; 연산이 실행되면 최대값(32,767)에 1을 더하게 되어, 값이 32,768이 된다.

    • 하지만 short 자료형은 16비트(2바이트)로 -32,768에서 32,767 사이의 값만 표현할 수 있다. 따라서 32,768을 저장할 수 없어 오버플로우가 발생하고, 값이 가장 작은 음수 값인 -32,768으로 변하게 되었다.

  2. unsigned short 자료형 오버플로우:

    • u_money 변수는 unsigned short 자료형으로 선언되었으며, USHRT_MAXunsigned short형의 최대값인 65,535로 초기화되었다.

    • u_money = u_money + 1; 연산이 실행되면 최대값(65,535)에 1을 더하게 되어, 값이 65,536이 되었다.

    • 하지만 unsigned short는 부호가 없는 정수형으로 0에서 65,535 사이의 값만 표현할 수 있다. 따라서 65,536을 저장할 수 없어 오버플로우가 발생하고, 값이 0으로 변하게 되었다.

오버플로우 결과

  • s_money: 32767 + 1 -> -32768

    • 부호가 있는 short 자료형의 경우, 최대값을 초과하면 가장 작은 음수 값으로 순환된다.
  • u_money: 65535 + 1 -> 0

    • 부호가 없는 unsigned short 자료형의 경우, 최대값을 초과하면 0으로 순환된다.

오버플로우 해결 방법

  • 더 큰 자료형을 사용:

    • 예를 들어, short 대신 int 또는 long 자료형을 사용하여 값의 범위를 넓힌다.

    • unsigned short 대신 unsigned int 또는 unsigned long을 사용하여 값의 범위를 확장할 수 있다.

  • 오버플로우 체크:

    • 값이 최대값에 도달하기 전에 if 조건문을 사용하여 오버플로우 여부를 확인할 수 있다.

    • 예시:

        if (s_money < SHRT_MAX) {
            s_money += 1;
        } else {
            printf("s_money의 최대값을 초과했습니다.\n");
        }
      

4️⃣ 상수의 자료형을 명시적으로 지정하기

(Explicitly specifying the data type of a constant)

기본 정수형 (Default Integer Type)

  • 기본적으로 숫자를 적으면 int형이 된다.

  • 예를 들어, 다음 코드에서 123이라는 숫자는 int 자료형으로 인식된다.

  • 예시:

      int sum = 123;  // 123은 int형으로 저장된다.
    

    즉, 별도의 자료형 접미사(suffix) 없이 숫자만 사용하는 경우, C 컴파일러는 기본적으로 int형으로 처리한다.

상수의 자료형을 명시적으로 지정하기
(Explicitly specifying the data type of a constant)

특정 숫자 리터럴(상수)의 자료형을 명시적으로 지정하고 싶을 때는 숫자 뒤에 접미사(suffix)를 붙여 해당 상수의 자료형을 나타낼 수 있다.

자료형 접미사 (Suffixes)

접미사자료형예시
u 또는 Uunsigned int123u 또는 123U
l 또는 Llong123l 또는 123L
ul 또는 ULunsigned long123ul 또는 123UL

사용 예시

  1. unsigned int 자료형 지정:

    • u 또는 U 접미사를 사용하여, 정수 상수를 unsigned int 자료형으로 지정할 수 있다.

    • 예시:

        unsigned int sum = 123U;  // 123은 unsigned int형으로 저장된다.
      
  2. long 자료형 지정:

    • l 또는 L 접미사를 사용하여, 정수 상수를 long 자료형으로 지정할 수 있다.

    • 예시:

        long sum = 123L;  // 123은 long형으로 저장된다.
      
  3. unsigned long 자료형 지정:

    • ul 또는 UL 접미사를 사용하여, 정수 상수를 unsigned long 자료형으로 지정할 수 있다.

    • 예시:

        eunsigned long sum = 123UL;  // 123은 unsigned long형으로 저장된다.
      

접미사를 사용하는 이유

접미사를 사용하여 상수의 자료형을 명시적으로 지정하는 이유는 정확한 자료형을 명시함으로써 연산의 결과를 예상 가능하게 하고, 오버플로우와 같은 문제를 방지할 수 있기 때문이다.

예를 들어, 다음과 같은 상황에서 자료형을 명시적으로 지정하는 것이 필요할 수 있다:

  1. 큰 값의 상수 표현:

    • int의 범위를 초과하는 큰 값이 필요한 경우, long이나 unsigned long으로 명시하여 컴파일러가 해당 값을 처리할 수 있도록 한다.

    • 예시:

        unsigned long bigValue = 3000000000UL;  // 큰 값을 unsigned long으로 지정
      
  2. 음수와 양수 간의 연산:

    • unsignedsigned 자료형 간의 연산에서는 자료형 변환이 발생할 수 있기 때문에, 명시적으로 unsigned 자료형을 사용하는 것이 좋다.

예제 코드: 접미사를 사용한 자료형 지정

다음 예제는 다양한 정수 상수와 접미사를 사용하는 코드이다.

#include <stdio.h>

int main() {
    int sum = 123;            // 기본적으로 int형
    unsigned int u_sum = 123U; // unsigned int형
    long l_sum = 123L;        // long형
    unsigned long ul_sum = 123UL; // unsigned long형

    printf("sum: %d\n", sum);
    printf("u_sum: %u\n", u_sum);
    printf("l_sum: %ld\n", l_sum);
    printf("ul_sum: %lu\n", ul_sum);

    return 0;
}

예제 출력

makefileCopy codesum: 123
u_sum: 123
l_sum: 123
ul_sum: 123

위 예제에서, 각 숫자 리터럴에 접미사를 사용하여 해당 변수의 자료형을 명시적으로 지정할 수 있다. 이를 통해 프로그램의 정확성과 안정성을 높일 수 있게된다.


5️⃣ 기호 상수(Symbolic constant)

기호 상수

기호 상수(symbolic constant)는 상수를 의미 있는 이름으로 정의하여 사용하는 것을 의미한다. 기호 상수는 프로그램에서 반복적으로 사용되는 값을 가독성 있게 표현하고, 값의 변경을 쉽게 할 수 있도록 도와준다.


기호 상수의 개념

기호 상수는 프로그램에서 자주 사용하는 숫자 상수 또는 문자열 상수의미 있는 이름을 부여하여 사용하는 것이다. 이를 통해 코드의 의미를 더 명확히 하고, 코드 유지보수 및 수정 작업을 용이하게 할 수 있다.

기호 상수 예시

  1. 실제 값 사용:

     won = 1120 * dollar;  // 실제 값(1120)을 직접 사용
    

    위 코드에서는 1120이 환율을 의미하지만, 코드만으로는 그 의미를 명확히 알기 어렵다.

  2. 기호 상수 사용:

     #define EXCHANGE_RATE 1120
     won = EXCHANGE_RATE * dollar;  // 기호 상수 EXCHANGE_RATE 사용
    

    위 코드에서는 EXCHANGE_RATE라는 기호 상수를 사용하여 1120을 대체했다. 이제 코드만 보아도 EXCHANGE_RATE가 환율을 의미한다는 것을 쉽게 파악할 수 있다.


기호상수의 장점

  • 가독성 향상(Improved readability)

    • 숫자나 문자열 값을 직접 사용하는 대신, 의미 있는 이름으로 기호 상수를 사용하면 코드의 가독성이 높아진다.

    • 예: won = EXCHANGE_RATE * dollar;won = 1120 * dollar;보다 코드의 의미를 더 명확하게 전달할 수 있다.

  • 값의 변경 용이성(Ease of value modification)

    • 기호 상수는 한 번만 정의해두면, 코드 전체에서 해당 기호를 사용하여 값을 참조할 수 있다. 따라서 값이 변경될 때, 기호 상수를 정의한 부분만 수정하면 코드 전체에 변경 사항이 반영된다.

    • 예: 환율이 변경되면 #define EXCHANGE_RATE 1150 한 줄만 수정하면 된다.

  • 코드 오류 방지 (Prevention of code errors)

    • 상수를 일일이 숫자로 사용하면 타이핑 실수나 잘못된 값 입력으로 인해 오류가 발생할 수 있다. 기호 상수를 사용하면 이러한 실수를 줄일 수 있다.

#define 기호이름 값
  • #define: 전처리기 지시어로, 기호 상수를 선언할 때 사용한다.

  • 기호이름: 기호 상수의 이름(예: EXCHANGE_RATE).

  • : 기호 상수에 할당되는 실제 값(예: 1120).

예시

#define EXCHANGE_RATE 1120

위 코드에서는 EXCHANGE_RATE라는 기호 상수를 1120이라는 값으로 정의하고 있다. 이 선언을 통해 코드에서 EXCHANGE_RATE를 사용할 때마다 1120으로 대체된다.


기호 상수를 만드는 방법 #2

💡요약: const 키워드는 변수의 값을 변경하지 못하도록 상수화하여 사용할 때 사용된다. 이렇게 정의된 상수는 자료형을 가지며 자료형 검사와 디버깅에 용이하다. #define 지시어는 전처리기에서 단순 치환을 수행하지만, const 상수는 메모리에 저장되며 컴파일러의 자료형 검사도 수행된다. 이러한 특성 덕분에, const 키워드는 코드의 안정성과 가독성을 높이는 데 유용한 도구이다.

const 키워드를 사용한 기호 상수 선언

  • 형식:

      const 자료형 기호이름 = 값;
    
    • const: 상수를 의미하는 키워드로, 해당 변수의 값을 변경할 수 없도록 한다.

    • 자료형: 변수에 저장될 값의 자료형(예: int, float).

    • 기호이름: 기호 상수의 이름(예: EXCHANGE_RATE).

    • : 상수로 설정할 값(예: 1120).

예시 코드

const int EXCHANGE_RATE = 1120;

위 코드는 EXCHANGE_RATE라는 이름의 기호 상수를 1120이라는 값으로 정의하고 있습니다. const 키워드를 사용함으로써 EXCHANGE_RATE의 값은 프로그램 실행 도중 변경될 수 없다.


기호 상수의 예제