프로그래밍 C언어

연산자(Operators)와 형변환(Type Casting)

게임첫걸음 2024. 8. 9. 10:10

 연산은 우리가 알고있는 +, -, *, /, % 등을 표현하며 C언어에서도 그 연산식을 다룹니다. 그 기호로 표현한 코드들을 연산자라 표현한다. 이번 글은 그 연산자와 짧게 배운 형변환에 대해 알아보겠습니다. 아래는 사용할 코드 정리입니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <stdio.h>
 
void main()
{
    //연산자(Operators)
    const int lhs = 3, rhs = 5;
 
    printf("lhs + rhs: %d\n", lhs + rhs);
    printf("lhs - rhs: %d\n", lhs - rhs);
    printf("lhs * rhs: %d\n", lhs * rhs);
    printf("lhs / rhs: %d\n", lhs / rhs);           //%d를 쓰면 10진수의 정수만 표현하라는 뜻이기 때문에 소수점을 제외한 값 0이 출력
    //printf("lhs / rhs: %f\n", lhs / rhs);         //%f를 쓰면 정수형 int를 float 실수형으로 표현하라는 뜻이기 때문에 유효한 함수가 아님
    //형변환(Type Casting, Type Conversion): 자료형을 바꿔주는 것
    //자료형의 승격
    printf("lhs / rhs: %f\n", lhs / rhs); //변수의 자료형 int를 float값으로 바꾸지 않고 %f로 표현해달라하니 0.000000으로 표현함.
    printf("lhs / rhs: %f\n", (float)lhs / rhs);    //int lhs를 float lhs로 변환하여 3을 3.000000으로 변환해 계산함 //이 순간만 변환
    printf("lhs / rhs: %f\n", lhs / (float)rhs);    //위와 같은 출력값 //정수보다 실수가 더 정확도가 높기 때문에 컴퓨터는 계산할 때 실수가 포함되있다면 그걸 따라 계산함.
    printf("lhs %% rhs: %d\n", lhs % rhs);          //Debug를 하면 % r을 %r로 읽어서 이런 용어 잘 모른다고 알려준다. 때문에 %%라고 붙여야함.
 
    float f = 3.14f;
    //묵시적 형변환 (Implicit Type Casting)
    //명시적 형변환 (Explicit Type Casting)
    int i = (int)f;                                  //(int)를 빼면 묵시적 형변환인데 잘못하면 관련 데이터 잃을 수 있음,(int)를 붙이면 명시적 형변환 //Debug할 때 "야, 너 f를 int로 형 변환하는 거 알아? 라고 얘기하는것.
    printf("i: %d\n", i);                            //%d이기 때문에 3.14의 소수 0.14를 제외하고 '3' 출력
 
    //float result = 3.14f % 0.5f;                   //나머지 연산(%)은 정수만 가능
 
    //단항연산자 ++, --은 1씩 증가, 감소를 얘기함.
    int value = 0;
    //후증가 연산자(Post-Increment)
    printf("value++ %d\n", value++);                 //%d\n처리를 먼저한 후, 후연산 출력값 0;
    //선증가 연산자(Pre-Increment)
    printf("++value: %d\n"++value);                //먼저 선연산 후 %d\n처리 진행 출력값 2;
    //후감소 연산자(Post-Decrement)
    printf("value--: %d\n", value--);                //%d\n처리를 먼저한 후, 후연산 출력값 2;
    //선감소 연산자(Pre-Decrement)
    printf("--value: %d\n"--value);                //먼저 선연산 후 %d\n처리 진행 출력값 0;
    //이러한 문제로 같은 조건과 결과라면 선연산이 속도가 빠르기 때문에 더 좋다.
    
    //대입연산자
    int result = lhs + rhs;
 
    //삼항연산자(조건 ?, 참: 거짓)
    result = lhs < rhs ? 0 : 1;                      // > < 비교연산자 조건 ? 참 : 거짓으로 lhs가 rhs보다 작으면 result값을 0으로 크면 1로 넣어라.
    printf("result: %d\n", result);
 
    //복합대입연산자
    long double val = 1.5L;
    val += 0.5L;                                     //val = val + 0.5L;
    val -= 0.5L;                                     //val = val - 0.5L;
    val *= 0.5L;                                     //val = val * 0.5L;
    val /= 0.5L;                                     //val = val / 0.5L;
    result %= 3;                                     // result 변수는 자료형이 int기 때문에 따로 표현. %나머지 연산은 정수로만 가능 3.3f이런거 안됨
 
    printf("Q1: 3 + 2 * 2 = %d\n"3 + 2 * 2);
    printf("Q2: ++result / result-- * ++result = %d\n"++result / result-- * ++result);
    printf("Q3: value = 3 + 2 / result-- = %f\n", value = 3 + 2 / (float)(result--));
 
    return;
}
cs

 

연산자에 관한 표

<연산자> (Operators)

앞 글에서 다뤘던 상수 선언으로 시작합니다.

void main()
{
//연산자(Operators)
const int lhs = 3, rhs = 5;

printf("lhs + rhs: %d\n", lhs + rhs);       // lhs + rhs: 8
printf("lhs - rhs: %d\n", lhs - rhs);        // lhs - rhs: -2
printf("lhs * rhs: %d\n", lhs * rhs);        // lhs * rhs: 15
printf("lhs / rhs: %d\n", lhs / rhs);         // lhs / rhs: 0
printf("lhs / rhs: %f\n", lhs / rhs);          // lhs / rhs: 0.000000      
printf("lhs / rhs: %f\n", (float)lhs / rhs); // lhs + rhs: 0.600000
printf("lhs / rhs: %f\n", lhs / (float)rhs); // lhs + rhs: 0.600000
printf("lhs %% rhs: %d\n", lhs % rhs);  // lhs % rhs: 3

 

float result = 3.14f % 0.5f;                    // %는 나머지 연산으로 정수만 가능하기 때문에 오류가 발생한다.

 

return;

}

const는 초기값이 고정된 상수로 lhs = 3과 rhs = 5가 선언되었습니다. 각 코드별 오른쪽 주석은 결과값입니다. +, -, *는 정수값에서 변화가 없으니 넘어가고 / 부터 보겠습니다.

 

printf("lhs / rhs: %d\n", lhs / rhs);         // lhs / rhs: 0                 // %d는 정수로 출력하라는 뜻, 소수 출력 X
printf("lhs / rhs: %f\n", lhs / rhs);          // lhs / rhs: 0.000000    // 정수 자료형인 int에 %f로 출력해달라하면 컴퓨터가 이해할 수 없어서 그냥 0.000000으로 표기하며 오류 발생
printf("lhs / rhs: %f\n", (float)lhs / rhs); // lhs + rhs: 0.600000   // 정수 상수인 lhs 값을 이 코드에선 임의로 실수형으로 바꿔 연산해달라는 뜻입니다. 그렇기 때문에 %f를 해도 오류가 없습니다.
printf("lhs / rhs: %f\n", lhs / (float)rhs); // lhs + rhs: 0.600000   // 정수 상수인 rhs 값을 이 코드에선 임의로 실수형으로 바꿔 연산해달라는 뜻입니다. 그렇기 때문에 %f를 해도 오류가 없습니다.

printf("lhs %% rhs: %d\n", lhs % rhs);  // lhs % rhs: 3              // %%를 한 이유는 Debug 시 %만 존재하면 % r로 읽어 해석할 수 없다고 경고가 발생하며 오류가 발생할 수 있습니다.

 

여기서 확인해야할 사항 3가지입니다.

  1. 실수 자료형을 정수로 출력해달라하면 소수값을 제외한 정수값만 출력합니다.
  2. 정수 자료형을 실수로 출력해달라하면 오류가 발생합니다. (컴퓨터가 이해 못함.)
  3. 정수 자료형을 실수형으로 변환시켜 실수로 출력해달라하면 가능합니다.

위의 3번에 대한 설명을 위해 잠시 형변환에 대해 설명하겠습니다.

 

<형변환> (Type Casting)

형변환의 종류는 두 가지로 묵시적(Implicit)과 명시적(Explicit)으로 나뉩니다.

 

float f = 3.14f;
int i = (int)f; 
printf("i: %d\n", i);

 

위 코드에서 f 변수는 실수로 선언되며 3.14f의 초기값을 가지고 있습니다. 그리고 다음 줄에서 int i = (int)f 라는 코드가 붙여지는데 그 뜻은 정수 i 변수의 초기값은 f 변수의 초기값의 정수 부분을 뜻합니다. 여기서 (int)가 붙은 상태를 명시적 형변환이라고 하고 붙이지 않으면 묵시적 형변환이라고 합니다.

묵시적 형변환이 가능한 자료형

위의 표대로라면 묵시적 형변환을 하여도 되지만 Debug시 경고해주며 잘못하면 관련 데이터를 잃을 수 있습니다. 때문에 웬만해선 명시적 형변환을 사용하는걸 생활화합시다.

 

<단항(증감) 연산자> (++, -- 1씩 증가, 감소)

 단항 연산자는 특정 변수, 상수끼리의 연산이 아니라 기존의 변수, 상수에 지속적인 특정값을 더하거나 빼는 것을 뜻합니다. 관련 코드를 위에서 가져옵니다.

 

int value = 0;
printf("value++ %d\n", value++);  //후증가 연산자(Post-Increment), %d\n처리를 먼저한 후, 후연산 출력값 0;
printf("++value: %d\n", ++value); //선증가 연산자(Pre-Increment), 먼저 선연산 후 %d\n처리 진행 출력값 2;
printf("value--: %d\n", value--);    //후감소 연산자(Post-Decrement), %d\n처리를 먼저한 후, 후연산 출력값 2;
printf("--value: %d\n", --value);    //선감소 연산자(Pre-Decrement), 먼저 선연산 후 %d\n처리 진행 출력값 0;

 

코드 우측 주석 설명대로 ++, --가 앞에 붙으면 선, 뒤에 붙으면 후라는 이름이 붙습니다. 순서에 따라 연산 순서도 달라집니다. 만약 같은 조건과 결과라면 선연산이 속도가 빠르기 때문에 더 활용하기 좋습니다.

위의 출력 순서는 %d 출력0 -> ++ -> ++ -> %d 출력2 -> %d 출력2 -> -- -> -- -> %d 출력0

 

<대입연산자>

대입 연산자는 = 등호에 관한 것으로 변수에 값, 변수, 수식 등을 대입한다라는 개념입니다. 밑의 코드에 주석 설명입니다.

int main()
 {
    int a, b, c, d, e;
    char f;
 
    a = 100;     // 변수 x에 정수 100 저장
    b = a;         // 변수 y에 변수 x 저장
    c = a + b;   // 변수 z에 x + y 수식의 결과(200) 저장

    d = e = 1;   // 다중대입(변수 a와 b에 정수 1 저장)

    f = 'C';     // 변수 ch에 문자 'a'를 저장
 

}

 

<삼항연산자> (조건 ?, 참 : 거짓)

비교 연산자 > <와 조건 ? 참 : 거짓을 다루는 연산자입니다. 위의 코드와 주석으로 설명합니다.

result = lhs < rhs ? 0 : 1;             // lhs = 3, rhs = 5라는 상수
printf("result: %d\n", result);        // lhs가 rhs보다 작으면 result값을 0으로 크면 1로 넣어라.

결과값은 0이 나옵니다.

 

<복합대입연산자>

복합대입연산자는 대입 연산자 = 등호에 여러 연산자를 붙여 사용하는 것을 의미합니다. 위의 코드를 가져옵니다.

const int lhs = 3, rhs =5;

 

int result = lhs + rhs;

long double val = 1.5L;


val += 0.5L;     //val = val + 0.5L;
val -= 0.5L;      //val = val - 0.5L;
val *= 0.5L;      //val = val * 0.5L;
val /= 0.5L;       //val = val / 0.5L;
result %= 3;     //result = result % 3; (result = result / 3의 나머지값) result 변수는 자료형이 int기 때문에 따로 표현. %나머지 연산은 정수로만 가능하기 때문에 실수형인 val 대신 정수형 변수인 result로 표현함, 출력값에 3.3f 이런거 나올 수 없습니다.

 

코드 우측 주석의 설명대로 복합대입연산자의 코드는 <변수명 - 복합대입연산자 - 식>으로 구성되어있으며 있습니다. 이제 val과 result 코드들을 출력해보겠습니다.

 

printf("val += %lf\n", val += 0.5L);          //출력값 val += 2.000000
printf("val -= %lf\n", val -= 0.5L);            //출력값 val -= 1.500000
printf("val *= %lf\n", val *= 0.5L);           //출력값 val *= 0.750000
printf("val /= %lf\n", val /= 0.5L);            //출력값 val /= 1.500000
printf("result %= %d\n", result %= 3);    //출력값 result %= 2        

 

여기서 기억해야할건 val의 값은 상수가 아닌 변수이기 때문에 위에서 아래로 코드가 내려가며 var의 값은 항시 변하게됩니다. 즉, += 연산 출력값인 2.000000이 -= 연산에 대입되어 출력되고 그 값이 *=에 출력되고 이러한 방식으로 진행되어 주석에 나온 출력값이 나오게 된다. %=는 나머지값을 나타내는 것이기 때문에 2가 나오게된다.

 

'프로그래밍 C언어' 카테고리의 다른 글

반복문(Loop)  (1) 2024.08.11
분기문(Branch)과 조건문(Condition)  (0) 2024.08.09
변수(Variable)와 상수(Constant)  (0) 2024.08.08
고정소수점과 부동소수점의 이해  (0) 2024.08.08
변수와 자료형(Data Type)  (0) 2024.08.07