# 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?)**

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

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

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

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

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

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

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

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

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

1. **가독성(Readability)**
    
    * 변수를 사용하지 않는 코드(`area = 100 * 200;`)는 단순히 숫자만 나열되어 있어서, 나중에 코드를 볼 때 100과 200이 무엇을 의미하는지 이해하기 어려울 수 있다.
        
    * 반면에 변수를 사용한 코드(`width = 100; height = 200; area = width * height;`)는 `width`와 `height`라는 변수명을 통해 코드의 의미를 쉽게 파악할 수 있다.
        
2. **유지보수 용이성(Easy maintenance)**
    
    * 변수를 사용하지 않은 코드에서는 값을 변경할 때마다 모든 관련 부분을 수정해야 하는 번거로움이 있다.
        
    * 변수를 사용한 코드에서는 값만 수정하면 이를 참조하는 모든 곳에서 자동으로 반영된다. 예를 들어, `width`나 `height` 변수를 변경하면 `area` 값도 자동으로 갱신된다.
        
3. **재사용성(Reuasable)**
    
    * 변수를 사용하면 같은 변수명을 사용하여 다양한 연산과 기능에 재사용할 수 있어, 코드의 효율성을 높일 수 있다.
        

---

**변수와 상수(Variable and constant)**

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

**변수 (Variable)**

* **정의**: 변수는 값이 변경될 수 있는 메모리 공간이다.
    
* **특징**: 프로그램 실행 도중 변수에 저장된 값을 변경할 수 있다.
    
* **예시**:
    
    ```plaintext
    # 변수 사용 예시
    score = 50       # 초기값 50 할당
    score = 100      # 값 변경 (50 → 100)
    print(score)     # 출력: 100
    ```
    
    위 예제에서 `score`라는 변수는 50에서 100으로 값이 변경될 수 있는 공간이다.
    

**상수 (Constant)**

* **정의**: 상수는 값이 한 번 저장되면 변경할 수 없는 메모리 공간이다.
    
* **특징**: 프로그램 실행 도중 값이 변하지 않으므로, 값이 고정된 데이터를 표현할 때 사용한다.
    
* **예시**:
    
    ```plaintext
    # 상수 사용 예시 (파이썬에서는 상수를 별도로 지원하지 않지만, 변수명을 대문자로 사용하여 관례적으로 표현)
    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)**

### 코드 분석

```c
#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`: 원의 면적을 저장하는 변수.
        
    
    이 두 변수는 사용자가 입력한 값과 계산된 값을 저장할 수 있으며, 프로그램 실행 도중 여러 번 값이 변경될 수 있다.
    
2. **상수 (**`3.141592`)
    
    * `3.141592`는 원의 면적을 계산할 때 사용되는 **원주율**로, 값이 변경되지 않는 상수입니다.
        
    * 원주율을 코드 내에서 직접 사용하지 않고 상수로 정의하는 것이 일반적이다. 상수를 사용하면 원주율 값이 변경될 일이 있을 때, 코드 전체를 수정할 필요 없이 상수 값만 변경하면 된다.
        

**개선된 상수 사용 예시**

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

```c
#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)

**자료형**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727490690018/a8896104-6022-4891-ad8e-c6d10243fad6.png align="center")

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

**자료형의 종류**

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

1. **정수형 자료형(integer)**: 정수형 자료형은 소수점이 없는 정수 데이터를 저장한다.
    
    * **short**: 메모리를 적게 사용하며, -32,768에서 32,767 사이의 정수를 저장할 수 있다.
        
    * **int**: 일반적으로 사용되는 정수형으로, -2,147,483,648에서 2,147,483,647까지의 정수를 저장할 수 있다.
        
    * **long**: 더 큰 범위의 정수를 저장할 수 있으며, 메모리도 더 많이 사용한다.
        
    
    **예시**:
    
    ```c
    num1 = 100;    // short형 변수
    int num2 = 1000;     // int형 변수
    long num3 = 100000;  // long형 변수
    ```
    
2. **부동소수점형 자료형(Floating point)**: 실수 데이터를 저장하며, 정밀한 소수점을 표현할 수 있다.
    
    * **float**: 단정도 실수형으로 소수점 이하 6~7자리 정도의 정밀도를 가진다.
        
    * **double**: 배정도 실수형으로 소수점 이하 15~16자리 정도의 정밀도를 가진다. `float`보다 더 많은 메모리를 사용하며, 더 정밀한 실수 데이터를 표현할 수 있다.
        
    
    **예시**:
    
    ```c
    num1 = 3.14f;      // float형 변수 (f를 붙여야 함)
    double num2 = 3.141592;  // double형 변수
    ```
    
3. **문자형 자료형(character)**: 하나의 문자 데이터를 저장한다.
    
    * **char**: 1바이트(= 8 비트) 크기의 문자형 자료형으로, 하나의 문자('A', 'B', '1', '한' 등)를 저장할 수 있다.
        
    
    **예시**:
    
    ```c
    letter = 'A';    // char형 변수에 문자 'A' 저장
    char korean = '한';    // char형 변수에 문자 '한' 저장
    ```
    

---

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727491200333/d2777f1d-32bf-41fc-8b89-7583c52c88a4.png align="center")

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

**비유 설명**

1. **물건이 상자보다 큰 경우**:
    
    * **설명**: 만약 물건이 상자보다 크면, 상자 안에 물건을 넣을 수 없게 된다.
        
    * **프로그래밍 비유**: 예를 들어, `short` 자료형의 변수에 매우 큰 수(예: 1,000,000)를 저장하려고 하면, 자료형의 크기를 초과하여 값이 제대로 저장되지 않거나 오류가 발생할 수 있다.
        
2. **물건이 상자보다 작은 경우**:
    
    * **설명**: 물건이 상자보다 지나치게 작으면, 상자 안에 공간이 많이 남아 비효율적이다.
        
    * **프로그래밍 비유**: 예를 들어, 단순한 정수(1, 2, 3)를 저장하려고 하는데 `long` 자료형(8바이트)을 사용하면, 불필요하게 큰 메모리 공간이 할당되어 메모리 낭비가 발생하게 된다.
        

---

**자료형의 분류**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727491903962/b73a1d11-4401-433f-b3b8-4880379d1fd8.png align="center")

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

**자료형의 크기**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727491985385/9c71e695-b616-4962-ad0b-6da580a543ef.png align="center")

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

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

`sizeof` **연산자 사용 방법**

1. **변수의 크기 확인**: 특정 변수가 메모리에서 얼마나 많은 공간을 차지하는지 확인할 수 있다.
    
    ```c
    int number;
    printf("number 변수의 크기: %zu 바이트\n", sizeof(number));  // 출력: 4 바이트
    ```
    
2. **자료형의 크기 확인**: 특정 자료형이 메모리에서 얼마나 많은 공간을 차지하는지 확인할 수 있다.
    
    ```c
    printf("int 자료형의 크기: %zu 바이트\n", sizeof(int));  // 출력: 4 바이트
    printf("double 자료형의 크기: %zu 바이트\n", sizeof(double));  // 출력: 8 바이트
    ```
    
3. **배열이나 구조체의 크기 확인**: 배열이나 사용자 정의 구조체의 크기도 확인할 수 있다.
    
    ```c
    int arr[10];
    printf("배열 arr의 크기: %zu 바이트\n", sizeof(arr));  // 출력: 40 바이트 (int형이 4바이트이므로 4 x 10)
    ```
    

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

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

```c
#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;
}
```

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

```c
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)**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727492385926/134b16e4-47ca-485c-80b4-551b062647c3.png align="center")

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

* `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` 네 가지로 나뉘며, 각 자료형이 차지하는 **비트 크기**와 **저장 가능한 값의 범위**는 다음과 같다.

| 자료형 | 비트 크기 | 저장할 수 있는 값의 범위 |
| --- | --- | --- |
| **short** | 16비트 (2바이트) | \-32,768 ~ 32,767 |
| **int** | 32비트 (4바이트) | \-2,147,483,648 ~ 2,147,483,647 |
| **long** | 32비트 (4바이트) | \-2,147,483,648 ~ 2,147,483,647 |
| **long long** | 64비트 (8바이트) | \-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 |

**각 자료형의 크기와 비교**

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

* **int**와 **long**은 일반적으로 32비트(4바이트)를 차지하며, 정수형 자료형의 기본 크기로 사용된다. 일부 시스템에서는 `long` 자료형이 64비트를 차지할 수도 있다.
    
* **long long**은 64비트(8바이트)로 가장 큰 크기의 정수형 자료형이다. 큰 수를 표현할 때 사용된다.
    

**정수형 자료형 선택의 기준**

1. **short**: 작은 범위의 정수 값을 저장할 때 사용한다. 예를 들어, 학생의 나이, 학년 등.
    
2. **int**: 일반적으로 정수형 변수를 선언할 때 기본으로 사용된다. `int`는 대부분의 연산에서 성능과 메모리 측면에서 적절한 균형을 제공한다.
    
3. **long**: `int`와 같은 크기이지만, 일부 시스템에서는 더 큰 범위의 정수를 저장할 수 있도록 `long`이 64비트로 설정될 수 있다.
    
4. **long long**: 아주 큰 정수 값이 필요한 경우 사용한다. 예를 들어, 큰 숫자 연산이나 대용량 데이터 처리가 필요한 경우.
    

---

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727493171254/483c4836-16cd-47a0-a1d0-12b4d07c0e1b.png align="center")

* 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)
        

---

**예제**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727493551573/91178329-295a-4e5f-a65f-86a088f79938.png align="center")

---

**Signed, unsigned modifier (수식자)**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727493755250/ac605b43-c4e5-4311-acc9-24c8968ca3d2.png align="center")

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

<mark>💡요약: </mark> `signed`와 `unsigned` 수식자는 정수형과 문자형 변수의 **부호**를 결정한다.

* `unsigned`는 양수 값만 표현하고, `signed`는 음수와 양수를 모두 표현한다.
    
* `unsigned`는 비트를 더 많이 활용하여 더 넓은 양수 범위를 표현할 수 있지만, 음수를 다룰 때는 사용할 수 없다.
    
* 데이터를 정확하게 표현하기 위해서는 값의 범위를 고려하여 `signed`와 `unsigned`를 적절히 선택해야 한다.
    

**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을 의미합니다.
        

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727494275828/672e9a1e-c777-4c42-b0d1-9d944fb511e9.png align="center")

#### 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 char`와 `unsigned char`로 나눌 수 있다.
        
    * `signed char`는 -128에서 127까지, `unsigned char`는 0에서 255까지 표현할 수 있다.
        
    * `char` 자료형을 문자(예: 'A', 'B')로 사용할 때는 부호가 필요 없기 때문에 대부분 `unsigned char`를 사용한다.
        

---

**Unsigned 예제**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727494400495/a71d2ae4-a1e5-44e7-84e6-0428315ef400.png align="center")

---

## **3️⃣** 오버플로우 (Overflow)

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727495599363/178efe2a-50ea-4d52-a172-9bf7c2053bfa.png align="center")

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

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

* 부호가 있는 정수형(`signed`)에서는 최대값을 초과하면 가장 작은 음수 값으로, 부호가 없는 정수형(`unsigned`)에서는 `0`으로 순환된다.
    
* 오버플로우를 방지하기 위해서는 더 큰 자료형을 사용하거나, 값의 범위를 확인하는 조건문을 추가하여 코드를 작성하는 것이 좋다.
    

---

**오버플로우의 원인**

1. `short` 자료형 오버플로우:
    
    * `s_money` 변수는 `short` 자료형으로 선언되었으며, `SHRT_MAX`는 `short`형의 최대값인 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_MAX`는 `unsigned 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` -&gt; `-32768`
    
    * 부호가 있는 `short` 자료형의 경우, 최대값을 초과하면 가장 작은 음수 값으로 순환된다.
        
* `u_money`: `65535 + 1` -&gt; `0`
    
    * 부호가 없는 `unsigned short` 자료형의 경우, 최대값을 초과하면 `0`으로 순환된다.
        

---

**오버플로우 해결 방법**

* **더 큰 자료형을 사용**:
    
    * 예를 들어, `short` 대신 `int` 또는 `long` 자료형을 사용하여 값의 범위를 넓힌다.
        
    * `unsigned short` 대신 `unsigned int` 또는 `unsigned long`을 사용하여 값의 범위를 확장할 수 있다.
        
* **오버플로우 체크**:
    
    * 값이 최대값에 도달하기 전에 `if` 조건문을 사용하여 오버플로우 여부를 확인할 수 있다.
        
    * 예시:
        
        ```c
        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` 자료형으로 인식된다.
    
* 예시:
    
    ```c
    int sum = 123;  // 123은 int형으로 저장된다.
    ```
    
    즉, 별도의 자료형 접미사(suffix) 없이 숫자만 사용하는 경우, C 컴파일러는 기본적으로 `int`형으로 처리한다.
    

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

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

#### 자료형 접미사 (Suffixes)

| 접미사 | 자료형 | 예시 |
| --- | --- | --- |
| `u` 또는 `U` | `unsigned int` | `123u` 또는 `123U` |
| `l` 또는 `L` | `long` | `123l` 또는 `123L` |
| `ul` 또는 `UL` | `unsigned long` | `123ul` 또는 `123UL` |

#### 사용 예시

1. `unsigned int` 자료형 지정:
    
    * `u` 또는 `U` 접미사를 사용하여, 정수 상수를 `unsigned int` 자료형으로 지정할 수 있다.
        
    * 예시:
        
        ```c
        unsigned int sum = 123U;  // 123은 unsigned int형으로 저장된다.
        ```
        
2. `long` 자료형 지정:
    
    * `l` 또는 `L` 접미사를 사용하여, 정수 상수를 `long` 자료형으로 지정할 수 있다.
        
    * 예시:
        
        ```c
        long sum = 123L;  // 123은 long형으로 저장된다.
        ```
        
3. `unsigned long` 자료형 지정:
    
    * `ul` 또는 `UL` 접미사를 사용하여, 정수 상수를 `unsigned long` 자료형으로 지정할 수 있다.
        
    * 예시:
        
        ```c
        eunsigned long sum = 123UL;  // 123은 unsigned long형으로 저장된다.
        ```
        

**접미사를 사용하는 이유**

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

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

1. **큰 값의 상수 표현**:
    
    * `int`의 범위를 초과하는 큰 값이 필요한 경우, `long`이나 `unsigned long`으로 명시하여 컴파일러가 해당 값을 처리할 수 있도록 한다.
        
    * 예시:
        
        ```c
        unsigned long bigValue = 3000000000UL;  // 큰 값을 unsigned long으로 지정
        ```
        
2. **음수와 양수 간의 연산**:
    
    * `unsigned`와 `signed` 자료형 간의 연산에서는 자료형 변환이 발생할 수 있기 때문에, 명시적으로 `unsigned` 자료형을 사용하는 것이 좋다.
        

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

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

```c
#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;
}
```

### 예제 출력

```c
makefileCopy codesum: 123
u_sum: 123
l_sum: 123
ul_sum: 123
```

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

---

## 5️⃣ 기호 상수(Symbolic constant)

**기호 상수**

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

---

**기호 상수의 개념**

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

**기호 상수 예시**

1. **실제 값 사용**:
    
    ```c
    won = 1120 * dollar;  // 실제 값(1120)을 직접 사용
    ```
    
    위 코드에서는 `1120`이 환율을 의미하지만, 코드만으로는 그 의미를 명확히 알기 어렵다.
    
2. **기호 상수 사용**:
    
    ```c
    #define EXCHANGE_RATE 1120
    won = EXCHANGE_RATE * dollar;  // 기호 상수 EXCHANGE_RATE 사용
    ```
    
    위 코드에서는 `EXCHANGE_RATE`라는 기호 상수를 사용하여 `1120`을 대체했다. 이제 코드만 보아도 `EXCHANGE_RATE`가 환율을 의미한다는 것을 쉽게 파악할 수 있다.
    

---

**기호상수의 장점**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727497592698/3e38177f-96ab-4445-aead-52e1f583e00e.png align="center")

* **가독성 향상(Improved readability)**
    
    * 숫자나 문자열 값을 직접 사용하는 대신, 의미 있는 이름으로 기호 상수를 사용하면 코드의 가독성이 높아진다.
        
    * 예: `won = EXCHANGE_RATE * dollar;`는 `won = 1120 * dollar;`보다 코드의 의미를 더 명확하게 전달할 수 있다.
        
* **값의 변경 용이성(Ease of value modification)**
    
    * 기호 상수는 한 번만 정의해두면, 코드 전체에서 해당 기호를 사용하여 값을 참조할 수 있다. 따라서 값이 변경될 때, 기호 상수를 정의한 부분만 수정하면 코드 전체에 변경 사항이 반영된다.
        
    * 예: 환율이 변경되면 `#define EXCHANGE_RATE 1150` 한 줄만 수정하면 된다.
        
* **코드 오류 방지 (Prevention of code errors)**
    
    * 상수를 일일이 숫자로 사용하면 타이핑 실수나 잘못된 값 입력으로 인해 오류가 발생할 수 있다. 기호 상수를 사용하면 이러한 실수를 줄일 수 있다.
        

---

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727497961975/e8382012-88ac-4b01-95aa-4c8acef6f93a.png align="center")

```c
#define 기호이름 값
```

* `#define`: 전처리기 지시어로, 기호 상수를 선언할 때 사용한다.
    
* `기호이름`: 기호 상수의 이름(예: `EXCHANGE_RATE`).
    
* `값`: 기호 상수에 할당되는 실제 값(예: `1120`).
    

#### 예시

```c
#define EXCHANGE_RATE 1120
```

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

---

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

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727497986881/22d51d5f-74a8-4b59-96a0-a59eea77d464.png align="center")

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

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

* **형식**:
    
    ```c
    const 자료형 기호이름 = 값;
    ```
    
    * `const`: 상수를 의미하는 키워드로, 해당 변수의 값을 변경할 수 없도록 한다.
        
    * `자료형`: 변수에 저장될 값의 자료형(예: `int`, `float`).
        
    * `기호이름`: 기호 상수의 이름(예: `EXCHANGE_RATE`).
        
    * `값`: 상수로 설정할 값(예: `1120`).
        

**예시 코드**

```c
const int EXCHANGE_RATE = 1120;
```

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

---

**기호 상수의 예제**

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1727498019973/cd7bff9e-2170-40ea-ba26-9e7ae13765f8.png align="center")

---
