본문 바로가기

C언어

C 언어 코딩 도장 4

 

덧셈, 뺄셈하기

정수의 덧셈과 뺄셈

덧셈은 + 연산자, 뺄셈은 - 연산자를 사용한다.

#include <stdio.h>

int main()
{
    int num1;
    int num2;

    num1 = 1 + 2;
    num2 = 1 - 2;

    printf("%d\n", num1);
    printf("%d\n", num2);

    return 0;
}

실수의 덧셈과 뺄셈

실수도 정수와 마찬가지고 + 연산자로 덧셈을 하고, - 연산자로 뺄셈을 하면 된다.

#include <stdio.h>

int main()
{
    float num1;
    float num2;

    num1 = 1.0f + 0.456789f;
    num2 = 1.0f - 0.456789f;

    printf("%f\n", num1);
    printf("%f\n", num2);

    return 0;
}

 

변수 하나에서 값을 더하거나 빼기

 

변수의 값을 더하거나 뺀 다음, 다시 자기 자신에 저장해주는 방법

#include <stdio.h>

int main()
{
    int num1 = 1;
    int num2 = 1;

    num1 = num1 + 2;
    num2 = num2 - 2;

    printf("%d\n", num1);
    printf("%d\n", num2);

    return 0;
}

 

프로그램을 실행하면 num1에서 2를 더한 값이 출력되고, num2에서 2를 뺀 값이 출력되는 것을 확인할 수 있다.

num1에 2를 더한 다음에 다시 num1에 저장하는 코드가 있다면, num1 + 2가 먼저 처리가 되고, num1에 3을 할당하는 코드가 처리돼서 최종적으로 num1에는 3이 들어가게 된다.

C 언어에서는 변수를 두 번 입력하지 않도록 덧셈 후 할당(+=), 뺄셈 후 할당(-=)이 제공된다.

#include <stdio.h>

int main()
{
    int num1 = 1;
    int num2 = 1;

    num1 += 2;
    num2 -= 2;

    printf("%d\n", num1);
    printf("%d\n", num2);

    return 0;

}

 

num1 += 2;는 num1 = num1 + 2;의 축약형이다. 같은 결과가 나온다는 것을 알 수 있다.

 

12.3 Quiz 완료

#include <stdio.h>

int main()
{
    int num1;
    int num2 = 5;

    num1 = 10 - num2;

    num1 += 95;

    printf("%d\n", num1);

    return 0;

}

12.5 심사문제 완료

num3 = num1 + num2;
num3 -= 4.5f;

▲ 정답으로 제출한 코드

 

증가, 감소 연산자 사용하기

증가 연산자 ++ : 값을 1 증가시킴

감소 연산자 -- : 값을 1 감소시킴

줄여서 증감 연산자라고 부른다.

 

정수에서는 1 증가, 1 감소시키지만 포인터 연산에서는 자료형 크기만큼 증가, 감소 시키기도 한다. (포인터 연산에 대해서는 Unit 59에서 자세히 다룰 예정)

 

변수의 값을 1 증가, 감소시키기

증가 연산자++는 변수 앞과 뒤에 붙일 수 있다. e.g. 변수++; ++변수;

#include <stdio.h>

int main()
{
    int num1 = 1;

    num1++;

    printf("%d\n", num1);

    return 0;
}

변수 num1에는 1이 들어있고, ++ 연산자로 값을 1 증가시켰다.

증가 연산자는 변수 자체의 값을 변화시킨다.

num1++;를 풀어서 쓰면 num1 = num1 + 1; num1 += 1;로 표현할 수 있다.

 

감소 연산자는 변수 앞 뒤에 붙일 수 있다. e.g. 변수--; --변수;

#include <stdio.h>

int main()
{
    int num1 = 2;

    num1--;

    printf("%d\n", num1);

    return 0;
}

감소 연산자 또한 변수 자체의 값을 변화시킨다.

num1--;를 풀어서 쓰면 num1 = num1 - 1; num1 -= 1;로 표현할 수 있다.

실수 자료형에 증감 연산자 사용하기

#include <stdio.h>

int main()
{
    float num1 = 2.1f;
    float num2 = 2.1f;

    num1++;
    num2--;

    printf("%f %f\n", num1, num2);

    return 0;
}

실수형 변수에 ++와 -- 연산자를 사용하면 값을 1 증가시키거나 감소시킨다.

증감 연산자를 사용하면 정수 부분만 바뀌고 소수점 이하의 자리에는 영향을 미치지 않는다.

 

문자 자료형에 증감 연산자 사용하기

문자 자료형도 증감 연산자를 사용할 수 있다.

#include <stdio.h>

int main()
{
    char c1 = 'b';
    char c2 = 'b';

    c1++;
    c2--;

    printf("%c %c\n", c1, c2);

    return 0;
}

문자 자료형도 실제로는 정수이기 때문에, 증감 연산자를 사용하면 1을 증가시키거나 감소시킨다.

문자 자료형에는 b의 ASCII 코드가 들어있기 때문에 ASCII 코드대로 1을 증가시키면 c가 되고, 1을 감소시키면 a가 된다.

 

증감 연산자의 위치에 따른 차이점 알아보기

증감 연산자는 변수 앞, 뒤에 모두 사용할 수 있다.

단독으로 증감 연산자만 사용했을 때는 큰 차이가 없지만, 연산자를 사용한 뒤 다른 변수에 할당할 때는 위치에 따라 큰 차이가 있다.

증감 연사자를 변수 뒤에 사용해보기

#include <stdio.h>

int main()
{
    int num1 = 2;
    int num2 = 2;
    int num3;
    int num4;

    num3 = num1++;
    num4 = num2--;

    printf("%d %d\n", num3, num4);

    return 0;
}

프로그램이 실행됐을 때, 변수의 값이 바뀌지 않고 2가 그대로 출력된다는 것을 볼 수 있다.

num3 = num1++;와 num4 = num2--;를 풀어서 쓰면 다음과 같다.

num3 = num1;
num1 += 1;

num4 = num2;
num2 -= 1;

이 부분은 증감 연산자의 가장 큰 특징인데, 이처럼 변수 뒤에 증감 연산자를 사용한 것을 후위(postfix) 연산자라고 한다.

동작 순서

1. 현재 변수의 값이 다른 변수에 할당 (값의 변동이 없음)

2. 증감 연산자가 수행되어 변수의 값이 1 증가(감소)

증감 연산자를 변수 앞에 사용해보기

#include <stdio.h>

int main()
{
    int num1 = 2;
    int num2 = 2;
    int num3;
    int num4;

    num3 = ++num1;
    num4 = --num2;

    printf("%d %d\n", num3, num4);

    return 0;
}

 

프로그램이 실행됐을 때, 변수의 값이 변화한 것을 알 수 있다.

num3 = ++num1; 와 num4 = --num2;를 풀어서 쓰면 다음과 같다.

num1 = num1 + 1;
num3 = num1;

num2 = num2 - 1;
num4 = num2;

변수 뒤에 증감 연산자를 사용한 것을 전위(prefix) 연산자라고 한다.

동작 순서

1. 증감 연산자가 수행되어 변수의 값이 1 증가(감소)

2. 변수의 바뀐 값이 다른 변수에 할당  

증감 연산자를 사용한 수, 함수의 인자로 사용해보기 

#include <stdio.h>

int main()
{
    int num1 = 2;
    int num2 = 2;

    printf("%d %d\n", num1++, num2--);
    printf("%d %d\n", ++num1, --num2);

    return 0;
}

printf 함수 안에서 변수 뒤에 증감 연산자를 사용하면 바뀌기 전의 값이 먼저 출력된 다음에 연산자가 동작하여 값이 바뀌므로 printf 함수로 다시 변수의 값을 출력해보면 바뀐 값이 표시된다.

#include <stdio.h>

int main()
{
    int num1 = 2;
    int num2 = 2;

    printf("%d %d\n", ++num1, --num2);
    printf("%d %d\n", num1, num2);

    return 0;
}

printf 함수 안에서 변수 앞에 증감 연산자를 사용하면 연산자가 먼저 동작하여 바뀐 값이 출력되므로 printf 함수로 다시 변수의 값을 출력해보면 같은 값이 표시된다.

 

※ 증감 연산자는 변수 앞에 오느냐 뒤에 오느냐에 따라 결과가 달라지므로 사용할 때 주의해야 한다.

 

13.5 Quiz 완료

#include <stdio.h>

int main()
{
    int num1 = 2;
    int num2 = 8;
    int num3;
    int num4;

    num1++;
    num3 = --num1;

    --num2;
    num4 = num2++;

    printf("%d\n", num3);
    printf("%d\n", num4);

    return 0;
}

13.7 심사문제 완료

num1++;
num2++;
c1--;

▲ 정답으로 제출한 코드

 

곱셈, 나눗셈하기

곱셈은 * 연산자, 나눗셈은 / 연산자를 사용한다.

수학에서 사용하는 ×, ÷ 기호는 사용할 수 없다.

정수 곱셈, 나눗셈 해보기 

#include <stdio.h>

int main()
{
    int num1;
    int num2;

    num1 = 2 * 3;
    num2 = 7 / 2;

    printf("%d\n", num1);
    printf("%d\n", num2); // 소수점을 사용하지 않고 최대한 나눌 수 있는 값을 나타냄

    return 0;
}

곱셈은 특별한 게 없지만, 나눗셈은 결과를 보면 3.5가 아닌 3이 나온다.

C 언어는 정수끼리 나눗셈을 하면 결과도 정수로 표현된다.

나눗셈에서 주의해야 할 점 : 나누는 수에 0이 들어가면 컴파일 에러가 발생한다.

만약 변수에 정수와 0을 저장해서 나누면 컴파일 ㅇ러는 발생하지 않지만 실행 시 에러가 발생한다.

#include <stdio.h>

int main()
{
    int num1 = 1;
    int num2 = 0;
    int num3;

    num3 = num1 / num2;

    printf("%d\n", num3);

    return 0;
}

이 때는 Ctrl + F5가 아니라 F5만 눌러서 디버깅 모드로 실행시킨다.

실행해보면 처리되지 않은 예외가 있다고 하면서 에러 메시지가 발생하는 것을 확인할 수 있다.

실수 곱셈, 나눗셈 해보기 

#include <stdio.h>

int main()
{
    float num1;
    float num2;

    num1 = 2.73f * 3.81f;
    num2 = 7.0f / 2.0f;

    printf("%f\n", num1);
    printf("%f\n", num2);

    return 0;
}

프로그램을 실행했을 때, 실수끼리 나눗셈을 하면 소숫점 이하까지 계산이 된다.

실수 계산에서 한 가지 특이한 점은 계산 결과에서 오차가 발생한다는 점이다.

2.73 * 3.81 = 10.4013인데, 10.401299가 나온다. 실수 계산의 오차는 모든 사칙연산에서 나타나는데, 현재는 어려운 문제이기 때문에 실무에서 실수를 쓸 때 실수 계산의 오차에 대한 적절한 처리가 필요하다.

https://dojang.io/mod/page/view.php?id=738

 

C 언어 코딩 도장: 85.4 실수 자료형의 오차

부동소수점 방식은 실수를 정확히 표현할 수 없는 문제가 있습니다. 다음 내용을 소스 코드 편집 창에 입력하고 실행해봅니다. float_rounding_error.c #include int main() { float num1 = 0.0f; float num2 = 0.1f; // 0

dojang.io

 

실수는 소스코드에서 0으로 직접 나누면 컴파일 에러가 발생하지만, 변수에 실수와 0을 저장해서 나누면 정수와 결과가 다르게 나타난다.

#include <stdio.h>

int main()
{
    float num1 = 1.0f;
    float num2 = 0.0f;
    float num3;

    num3 = num1 / num2;

    printf("%f\n", num3);

    return 0;
}

실숫값에 0을 나누면 실행이 중단되지 않고 무한대(inf)가 나온다.

https://dojang.io/mod/page/view.php?id=739

 

C 언어 코딩 도장: 85.5 실수의 무한대와 숫자가 아닌 값 검사

C 언어에서 무한대를 검사하는 방법은 다음과 같습니다. float_infinity.c #include #include // 실수 자료형의 양수 최솟값, 최댓값이 정의된 헤더 파일 #include // 무한대 INFINITY가 정의된 헤더 파일 int main()

dojang.io

 

변수 하나에서 값을 곱하거나 나누기

 

변수 하나에 값을 곱하거나 나누는 방법

변수1 = 변수 * 값;

변수1 = 변수 / 값;

#include <stdio.h>

int main()
{
    int num1 = 2;
    int num2 = 7;

    num1 = num1 * 3;
    num2 = num2 / 2;

    printf("%d\n", num1);
    printf("%d\n", num2);

    return 0;
}

 

곱셈과 나눗셈도 변수를 두 번 입력하지 않도록 곱셈 후 할당 (*=), 나눗셈 후 할당 (/=) 연산자를 제공한다

변수 *= 값

변수 /= 값

#include <stdio.h>

int main()
{
    int num1 = 2;
    int num2 = 7;

    num1 *= 3;
    num2 /= 2;

    printf("%d\n", num1);
    printf("%d\n", num2);

    return 0;
}

14.3 Quiz 완료

#include <stdio.h>

int main()
{
    int base = 20;
    int height = 16;
    int area;

    area = base * height / 2;

    printf("%d\n", area);

    return 0;
}

 

14.5 심사문제 완료

radius = diameter / 2;
area = radius * radius * M_PI;

▲ 정답으로 제출한 코드

 

나머지 연산하기

나머지 연산을 따로 제공하는 이유?

나머지 연산은 나눗셈과 깊은 관계가 있다. 정수끼리 나눗셈을 하면 결과는 나누어 떨어지지 않고 소수점을 사용하지 않고 최대한 나눌 수 있는 값을 나타내게 되는데, 이 때 완전히 나누어지지 않는 나머지를 구하는 연산이 나머지 연산이다.

나머지 연산자 % (modular)

a % b

#include <stdio.h>

int main()
{
    printf("%d\n", 1 % 3);
    printf("%d\n", 2 % 3);
    printf("%d\n", 3 % 3);
    printf("%d\n", 4 % 3);
    printf("%d\n", 5 % 3);
    printf("%d\n", 6 % 3);

    return 0;
}

나머지 연산자는 앞에 숫자를 뒤에 숫자로 나눈 뒤 나머지를 구한다. 만약 완전히 나누어진다면 나머지는 0이다.

나머지 연산자는 특정수의 배수인지 알아볼 때 자주 사용한다.

어떤 수이든 특정 가지의 상태로 강제할 때도 사용할 수 있다.

나머지 연산자는 정수에서만 사용할 수 있고, 실수에서는 사용할 수 없으며, 0으로 나눈 결과의 나머지도 구할 수 없다.

더보기

실수의 나머지 구하기

실수끼리 나누었을 때 나머지는 math.h 헤더 파일의 fmod(double형 실수), fmodf(float형 실수), fmodl(long double형 실수) 함수로 구할 수 있다.

  • fmod(나누어지는 수, 나누는 수);

 

#include <stdio.h>
#include <math.h>

int main()
{
    double num1 = 10.843;
    double num2 = 3.79;
    printf("%f\n", fmod(num1, num2));

    float num3 = 10.843f;
    float num4 = 3.79f;
    printf("%f\n", fmodd(num3, num4));

    long double num5 = 10.843l;
    long double num6 = 3.79l;
    printf("%Lf\n", fmodl(num5, num6));

    return 0;
}

변수 하나에서 나머지 연산하기

변수1 = 변수1 % 값

변수에서 나머지를 구한 뒤 다시 변수에 할당해주는 방법이다.

#include <stdio.h>

int main()
{
    int num1 = 7;

    num1 = num1 % 2;

    printf("%d\n", num1);

    return 0;
}

 

나머지 연산도 변수를 두 번 입력하지 않도록 나머지를 구한 후 할당 (%=) 연산자를 제공한다.

#include <stdio.h>

int main()
{
    int num1 = 7;

    num1 %= 2;

    printf("%d\n", num1);

    return 0;
}

num1 %= 2;는 나머지 연산과 할당 연산을 동시에 처리한다. 단, 0으로 나머지 연산을 하지 않도록 주의해야 한다.

더보기

음수의 나머지 연산

C99 표준에서 나머지 연산자는 a == (a / b) * b + a % b로 정의하고 있다. 따라서 이 식에 대입해보면 a % b를 연산 했을 때 결과의 부호는 a의 부호를 따른다.(b의 부호는 무시)

15.3 Quiz 완료

#include <stdio.h>

int main()
{
    int num1 = 15;
    int num2 = 27;
    int num3 = 3;

    num1 %= num3;
    num2 %= num3;

    printf("%d\n", num1);
    printf("%d\n", num2);
    
    return 0;
}

15.5 심사문제 완료

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
    int num1;
    int num2;
    int num3;
    int num4;
    int num5;
    int num6;

    scanf("%d", &num1);

    num2 = num1 % 10;
    num3 = num1 % 100 / 10;
    num4 = num1 % 1000 / 100;
    num5 = num1 % 10000 / 1000;
    num6 = num1 / 10000;

    printf("%d %d %d %d %d\n", num2, num3, num4, num5, num6);

    return 0;
}

자료형의 확장과 축소 알아보기

자료형의 확장 알아보기

실제로 프로그래밍을 할 때는 서로 다른 자료형으로 연산을 할 때가 많다.

서로 다른 자료형끼리 연산 할 때는 정해진 규칙을 따른다.

#include <stdio.h>

int main()
{
    int num1 = 11;
    float num2 = 4.4f;

    printf("%f\n", num1 + num2);
    printf("%f\n", num1 - num2);
    printf("%f\n", num1 * num2);
    printf("%f\n", num1 / num2);

    return 0;
}

정수와 실수를 함께 연산하면 결과값은 실수로 나온다.

∵ 실수가 정수보다 표현 범위가 더 넓기 때문이다. (표현 범위가 넓은 쪽으로 자동 변환된다.)

C 언어에서는 자료형을 섞어서 쓰면 컴파일러에서 암시적 형 변환(implicit type conversion)을 하게 되는데 자료형의 크기가 큰 쪽, 표현 범위가 넓은 쪽으로 자동 변환되며, 이를 형 확장(type promotion)이라고 한다. 이는 값이 버려지지 않고 그대로 보전된다.

#include <stdio.h>

int main()
{
    long long num1 = 123456789000;
    int num2 = 10;

    printf("%lld\n", num1 + num2);
    printf("%lld\n", num1 - num2);
    printf("%lld\n", num1 * num2);
    printf("%lld\n", num1 / num2);

    return 0;
}

int는 4 Byte이고, long long은 8 Byte이기 때문에 int 보다 long long이 더 커서 long long으로 변환 된다.

 

자료형의 축소 알아보기

실수에서 정수로 표현 범위가 좁은 쪽으로 변환하게 되면 값의 손실이 생긴다.

#include <stdio.h>

int main()
{
    float num1 = 11.0f;
    float num2 = 5.0f;

    int num3 = num1 / num2;

    printf("%d\n", num3);

    return 0;
}

11.0에서 5.0을 나누면 2.2가 나오지만, 정수 자료형에서는 소수점 아래 숫자를 저장할 수 없기 때문에 0.2가 버려지게 된다.

이렇게 자료형의 크기가 작은 쪽, 표현 범위가 좁은 쪽으로 변환되는 것을 형 축소(type demotion)이라고 한다.

형 축소가 일어나면 값을 손실이 일어나는데, 컴파일 경고가 나오지 않게 하려면 형 변환(type conversion, type casting, 타입 캐스팅)을 해야 한다.

https://dojang.io/course/view.php?id=2&section=75

 

강좌: C 언어 코딩 도장, 섹션: Unit 58. 자료형 변환하기

변수를 다른 자료형을 변환하는 방법과 포인터, void 포인터, 구조체 포인터를 다른 자료형으로 변환하는 방법을 설명합니다.

dojang.io

 

#include <stdio.h>

int main()
{
    char num1 = 28;
    int num2 = 1000000002;

    char num3 = num1 + num2;

    printf("%d\n", num3);

    return 0;
}

char 자료형도 정수 자료형이기 때문에 int와 같이 연산을 해도 문제가 없다. 근데, char와 int를 같이 연산한 다음에 char에 저장하면 char보다 큰 수는 저장할 수 없다.

출처 : 코딩도장

형 축소가 일어나면 값이 버려질 수 있다는 점만 기억하면 된다.

출처 : 코딩도장

오른쪽으로 갈수록 크기가 크고 표현 범위가 넓은 자료형이고, 같은 자료형 안에서도 숫자가 높을수록 크기가 크다.

16.3 Quiz 완료

#include <stdio.h>

int main()
{
    char c1 = 'a';
    int num2 = c1;

    printf("%c\n", num2);

    return 0;
}

16.5 심사문제 완료

int num2 = num1;
printf("%d\n", num2);

▲ 정답으로 제출한 코드

'C언어' 카테고리의 다른 글

C 언어 코딩 도장 6  (0) 2025.01.13
C 언어 코딩 도장 5  (0) 2025.01.12
C 언어 코딩 도장 3  (0) 2025.01.09
C 언어 코딩 도장 2  (0) 2024.09.02
C 언어 코딩 도장 1  (0) 2024.07.21