Unit 8. 실수 자료형 사용하기
소숫점을 표현할 수 있는 실수 자료형의 크기와 저장할 수 있는 값의 범위는 다음과 같다.
파이썬에서 실수 자료형은 float 하나였는데 C에서는 위 3개의 자료형이 존재한다.
지수 표기법은 아주 큰 숫자나 아주 작은 숫자를 표현할 때 사용한다. 실수e + 지수는 실수 * 10의 거듭제곱이다. 또한 실수e - 지수는 실수 * 1/10의 거듭제곱이다.
long double의 크기는 운영체제의 플랫폼에 따라 다음과 같이 다르다.
컴퓨터에서는 값을 0과 1로 저장하기 때문에 실수고 0과 1로 저장해야 한다. 실수와 소수점을 2진수로 표현하는 방식을 부동소수점 표현 방식이라 한다. 부동소수점 방식은 자료형의 일정 부분을 비트 단위로 나누어 부호, 가수(significand), 기수(base), 지수(exponent)를 저장하여 실수를 표현한다.
다음과 같이 기수(n)을 지수(p)만큼 거듭제곱한 값을 가수(m)와 곱하는 방식이다. 가수는 2로 고정되어 있으며 2 자체는 따로 저장하지 않는다.
유효자릿수는 실수를 일정 자릿수만큼 표현할 수 있는 것이다. 만약 유효자릿수가 7이면 0.123456789는 반올림하여 0.123457로 표현된다. 정수부분 1자리와 소수부분 6자리로 7자리가 표현되는 것이다.
8.1 실수형 변수 선언하기
#include <stdio.h>
int main()
{
float num1 = 0.1f; // float는 숫자 뒤에 f를 붙임
double num2 = 3867.215820; // double는 숫자 뒤에 아무것도 붙이지 않음
long double num3 = 9.327513l; // long double는 숫자 뒤에 l을 붙임
printf("%f %f %Lf\n", num1, num2, num3);
return 0;
}
float에서 .1f, 1.f처럼 소숫점 앞 또는 뒤의 0은 생략할 수 있다.
실수를 출력할 때는 서식문자로 float와 double은 %f를, long double 는 %Lf를 사용한다.
지수표기법으로 실수를 저장하는 코드는 다음과 같다.
#include <stdio.h>
int main()
{
float num1 = 3.e5f; // 30000
double num2 = -1.3827e-2; // -0.013827
long double num3 = 5.21e+9l; // 5210000000
printf("%f %f %f %Lf\n", num1, num2, num3);
printf("%e %e %Le\n", num1, num2, num3);
return 0;
}
지수 표기법으로 실수를 출력할 때는 float, double는 서식지정자 %e를 사용하고, long double는 %Le를 사용한다. e뒤의 지수가 양수이면 num1과 같이 +기호를 생략할 수도 있다.
8.2 자료형 크기 구하기
다음과 같이 sizeof연산자를 이용하여 실수 자료형의 크기를 구할 수 있다.
#include <stdio.h>
int main()
{
float num1 = 0.0f;
double num2 = 0.0;
long double num3 = 0.0l;
printf("float : %d, double : %d, long double : %d",
sizeof(num1),
sizeof(num2),
sizeof(num3)
);
return 0;
}
윈도우 운영체제에서 각 자료형의 크기는 다음과 같다.
또한 mac OS에서의 각 자료형의 크기는 다음과 같다.
리눅스에서도 long double는 16바이트 이다.
8.3 최솟값과 최댓값 표현하기
실수 자료형의 양수 최솟값과 최댓값을 표현하는 방법은 다음과 같다. float.h 헤더파일에 실수 자료형별로 양수 최솟값과 최댓값이 정의되어 있다.
#include <stdio.h>
#include <float.h>
int main()
{
float num1 = FLT_MIN; // float의 양수 최솟값
float num2 = FLT_MAX; // float의 양수 최댓값
double num3 = DBL_MIN; // double의 양수 최솟값
double num4 = DBL_MAX; // double의 양수 최댓값
long double num5 = LDBL_MIN; // long double의 양수 최솟값
long double num6 = LDBL_MAX; // ling double의 양수 최댓값
printf("%.40f %.2f\n", num1, num2);
printf("%e %e\n", num3, num4);
printf("%Le %Le\n", num5, num6);
return 0;
}
서식지정자를 사용할때 %.40f, %.2f와 같이 .뒤에 숫자를 지정하면 해당 숫자만큼 출력하는 소숫점 자릿수를 설정할 수 있다.
double, long double의 최소, 최댓값들은 소수점 자리가 매우 길어 지수 표기법으로 출력하였다.
8.4 오버플로우와 언더플로우 알아보기
다음과 같이 실수 자료형도 오버플로우와 언더플로우가 발생할 수 있다.
#include <stdio.h>
#include <float.h>
int main()
{
float num1 = FLT_MIN;
float num2 = FLT_MAX;
num1 = num1 / 100000000.0f;
num2 = num2 * 1000.0f;
printf("%e %e\n",num1, num2);
return 0;
}
FLT_MIN을 10000000.0과 같이 아주 큰 값과 나누면 아주 작은 수가 되면서 언더플로우가 발생한다. C에서는 언더플로우를 0 또는 쓰레기값으로 처리한다.
FLT_MAX에 1000.0을 곱하면 저장할 수 있는 범위를 넘어서 오버플로우가 발생하게 된다. 실수는 오버플로우 발생 시 최솟값으로 되돌아가지 않고 무한대(inf)가 된다.
8.5 퀴즈
정답은 d이다.
정답은 e이다.
정답은 d이다. float는 실수 뒤에 f를 붙여야 한다.
정답은 b이다.
정답은 c이다.
8.6 연습문제 : 실수형 변수 선언하기
정답은 밑줄 순서대로 float, long double, double이다.
8.7 연습문제 : 자료형 크기 구하기
num1의 크기는 8이고, num2의 크기는 4이므로 정답은 순서대로 double, float이다.
8.8 연습문제 : 최솟값과 최댓값 표현하기
정답은 다음 코드와 같다.
#include <float.h>
DBL_MIN
LDBL_MAX
8.9 언더플로우
num1을 큰 수로 나누면 되므로 정답은 / 10000000.0f 이다.
8.10 심사문제 : 실수형 변수 선언과 자료형 크기 구하기
num1 의 크기는 4이니 float 이고, num2의 크기는 8이기 때문에 double이다. 정답은 다음 코드와 같다.
float num1 = 1.8f;
double num2 = 2.9;
8.11 심사문제 : 최솟값과 최댓값 표현하기
정답은 다음 코드와 같다.
doubleMin = DBL_MIN;
doubleMax = DBL_MAX;
longDoubleMin = LDBL_MIN;
longDoubleMax = LDBL_MAX;
8.12 심사문제 : 오버플로우
정답은 - FLT_MAX 이다.
Unit 9. 문자 자료형 사용하기
C에서는 정수 자료형 char을 사용하여 문자 1개를 저장한다. 문자 자료형의 저장 범위와 크기는 다음과 같다.
C에서 문자를 저장할 때는 아스키 코드이 문자에 해당하는 정수 값을 저장한다. 다음은 아스키 코드표 이다.
65(0x41)부터 90(0x5A)까지 알파벳 대문자를 나타내고, 97(0x61)부터 122(0x7A)까지 알파벳 소문자를 나타낸다. 나머지 값들은 공백, 특수문자, 숫자 등을 나타낸다.
C에서 문자는 다음과 같이 ' '(작은따옴표)로 묶어서 표현한다.
char c1 = 'a';
작은따옴표는 문자 하나만 묶을 수 있고, 두개 이상은 묶을 수 없다.
정수 자료형에 2바이트 값을 저장할 때는 다음과 같이 문자 두 개를 작은 따옴표로 묶기도 한다.
unsigned short magic = 'BA';
파이썬에서는 문자열로 여러개의 문자를 다른 선언 없이 변수에 저장할 수 있었지만 C는 이러한 것들이 불가능한 것 같다.
9.1 문자 변수 선언하기
#include <stdio.h>
int main()
{
char c1 = 'a';
char c2 = 'b';
printf("%c %d\n",c1 ,c1);
printf("%c %d\n", c1, c2);
return 0;
}
변수나 문자를 출력할 때는 %c 서식지정자를 사용한다. 서식 지정자로 %d를 사용하면 char 변수에 저장된 문자의 아스키 코드값이 10진수로 출력된다.
다음과 같이 작은따옴표로 문자를 저장하지 않고, 아스키 코드에 해당하는 정수로 문자를 출력할 수 있다.
#include <stdio.h>
int main()
{
char c1 = 97;
char c2 = 98;
printf("%c %d\n",c1 ,c1);
printf("%c %d\n", c2, c2);
return 0;
}
다음과 같이 아스키 코드값 16진수를 넣어서도 문자 자료형을 사용할 수 있다.
#include <stdio.h>
int main()
{
char c1 = 0x61;
char c2 = 0x62;
printf("%c %d 0x%x\n",c1 ,c1, c1);
printf("%c %d 0x%x\n", c2, c2, c2);
return 0;
}
16진수를 출력하려면 서식지정자 %x를 사용한다.(%X는 16진수의 알파벳을 대문자로 표시) 16진수만 출력하면 10진수와 구분하기 힘드므로 앞에 0x를 붙인다.
문자 자료형에 같은 숫자를 저장해도 문자 '0'과 숫자 0은 다르다.
#include <stdio.h>
int main()
{
char c1 = '0';
char c2 = 0;
printf("%c %d\n",c1 ,c1);
printf("%c %d\n", c2, c2);
return 0;
}
'0'을 10진수로 출력해보면 '0'의 아스키 코드값인 48이 나오며, 0을 문자로 출력하면 아스키 코드 0은 널문자를 뜻하므로 아무것도 출력되지 않는다.
9.2 문자로 연산하기
문자도 아스키 코드의 정수로 저장되므로 정수처럼 덧셈, 뺄셈을 할 수 있다.
#include <stdio.h>
int main()
{
printf("%c %d\n", 'a'+1, 'a'+1);
printf("%c %d\n", 97+1, 97+1);
return 0;
}
'a'의 아스키코드 값은 97이고, 'b'의 아스키코드 값은 98이기 때문에 'a' + 1은 'b'가 출력된다. 또한 97은 'a'이고, 98은 'b'이기 때문에 97 + 1 의 값은 'b'가 출력된다. char로 저장한 변수에 정수를 더하거나 빼도 결과는 같다.
9.3 제어문자 사용하기
문자 자료형에는 \n 과 같은 제어문자도 지정할 수 있다.
#include <stdio.h>
int main()
{
char c1 = 'a';
char c2 = 'b';
char lineFeed = '\n';
printf("%c%c%c%c", c1, lineFeed, c2, lineFeed);
return 0;
}
제어문자 '\n'이 저장된 변수 lineFeed를 %c로 출력하면 줄바꿈이 되어 위와 같이 출력된다. 다음은 자주 접하게 되는 제어문자의 아스키 코드 이다.
다음은 제어문자의 아스키 코드를 출력한 것이다.
#include <stdio.h>
int main()
{
char lineFeed = '\n';
printf("%d 0x%x\n", lineFeed, lineFeed);
return 0;
}
제어문자 \n의 10진수 값과 16진수 값인 10과 0xa가 출력되었다.
9.4 퀴즈
정답은 c이다.
정답은 e이다.
정답은 b이다.
9.5 연습문제 : 제어문자 사용하기
정답은 '\t'이다. 탭을 의미하는 제어문자는 \t이다.
9.6 연습문제 : 정수 숫자를 문자로 변환하기
출력을 %c로 하고 있고, 아스키코드로 2는 50이므로 48씩 더하면 된다. 따라서 정답은 +48, +48이다.
9.7 심사문제 : 제어문자 사용하기
c1 은 탭, c2는 줄바꿈, c3는 탭이 들어가야 하므로 정답은 다음과 같다.
c1 = '\t';
c2 = '\n';
c3 = '\t';
9.8 심사문제 : 알파벳 소문자를 대문자로 변환하기
a와 A는 아스키코드로 32 차이가 나므로 정답은 -32 이다.
Unit 10. 상수 사용하기
상수는 변하지 않는 값을 의미한다. 변수는 한 번 선언하고 값을 계속 바꿀 수 있지만, 상수는 선언되면 값을 바꿀 수 없다.
const int con1 = 10;
위와 같은 코드가 있을 때 con1을 상수라 하고, 10을 리터럴이라 한다. 리터럴은 값 자체를 의미하고, 상수는 변수처럼 리터럴이 저장된 공간이다. 상수는 값을 바꾸는 것을 방지하기 위해 사용하며 코드의 의도를 명확하게 만들 수 있다.
10.1 리터럴 사용하기
#include <stdio.h>
int main()
{
printf("%d\n", 10);
printf("%f\n", 0.1f);
printf("%c\n", 'a');
printf("%s\n", "Hello, world!");
return 0;
}
위 코드와 같이 변수에 저장하지 않고 값을 그대로 사용하는 것이 리터럴이다. 리터럴은 표기 방법을 반드시 지켜야 한다. 문자는 반드시 작은따옴표로 묶어야 하고, 문자열은 큰 따옴표로 묶어야 한다. 큰 따옴표로 묶은 문자열을 출력하려면 %s 서식지정자를 사용한다.
다음은 정수 리터럴의 표기 방법이다.
#include <stdio.h>
int main()
{
printf("%d\n", 19); // 10진 정수 리터럴
printf("0%o\n", 017); // 8진 정수 리터럴
printf("0x%X\n", 0x1F); // 16진 정수 리터럴
return 0;
}
8진수는 서식지정자로 %o를 사용한다. 8진수는 앞에 0을 붙이고, 16진수는 앞에 0x를 붙여 10진수와 구분하기 쉽게 한다.
실수 리터럴 표기는 다음과 같다.
#include <stdio.h>
int main()
{
printf("%f\n", 0.1F); // 실수 리터럴 소수점 표기
printf("%f\n", 1.0e-5f); // 실수 리터럴 지수 표기법
}
실수 리터럴이 float 크기면 끝에 f를 붙이고, long double크기라면 끝에 l 또는 L을 붙인다. 지수표기법은 e 또는 E와 지수를 표기한다.
10.2 상수 사용하기
자료형 앞에 const를 붙이면 상수를 사용할 수 있다.
#include <stdio.h>
int main()
{
const int con1 = 1;
const float con2 = 0.1f;
const char con3 = 'a';
printf("%d %f %c\n", con1, con2, con3);
return 0;
}
상수는 반드시 선언과 동시에 초기화 해야 하며 초기화 하지 않으면 컴파일 에러를 발생한다. 상수도 변수처럼 이름으로 저장된 값을 출력할 수 있다.
#include <stdio.h>
int main()
{
const int con1 = 1;
con1 = 2;
printf("%d\n", con1);
return 0;
}
위와 같이 상수에 값을 할당하면 이후에 값을 변경할 수 없다. const는 다음과 같이 자료형 뒤에 붙여도 된다.
int const con1 = 1;
10.3 정수 리터럴 접미사 사용하기
리터럴의 크기를 명확하게 하려면 접미사를 사용할 수 있다.
#include <stdio.h>
int main()
{
printf("%ld\n", -10L); // long 크기의 정수 리터럴
printf("%lld\n", -1234567890123456789LL); // long long 크기의 정수 리터럴
printf("%u\n", 10U); // unsigned int 크기의 정수 리터럴
printf("%lu\n", 1234567890UL); // unsigned long 크기의 정수 리터럴
printf("%lu\n", 10UL); // unsigned long 크기의 정수 리터럴
printf("%llu\n", 1234567890123456789ULL); // unsigned long long 크기의 정수 리터럴
return 0;
}
리터럴은 접미사를 사용하여 정수 자료형으로 크기를 정하는 것 처럼 리터럴의 크기를 명시적으로 표시할 수 있다. 정수 리터럴 접미사 목록은 다음과 같다.
접미사는 소문자와 대문자 모두 사용할 수 있고, u로 부호를, l로 크기를 표현한다.
다음과 같이 8진수와 16진수에서도 리터럴을 사용할 수 있다.
#include <stdio.h>
int main()
{
printf("0%lo\n", 017L);
printf("0%lo\n", 017UL);
printf("0x%lX\n", 0x7FFFFFL);
printf("0x%lX\n", 0xFFFFFFFFUL);
return 0;
}
10.4 실수 리터럴 접미사 사용하기
#include <stdio.h>
int main()
{
printf("%f\n", 0.1F); // float 크기의 실수 리터럴
printf("%f\n", 0.1); // double 크기의 실수 리터럴
printf("%Lf\n", 0.1L); // long double 크기의 실수 리터럴
printf("%f\n", 1.0e-5F); // float 크기의 실수 리터럴
printf("%f\n", 1.0e-5); // double 크기의 실수 리터럴
printf("%Lf\n", 1.0e-5l); // long double 크기의 실수 리터럴
return 0;
}
실수 리터럴 끝에 f를 붙이면 float크기가 되고, l을 붙이면 long double크기가 되고, 아무것도 붙이지 않으면 double크기가 된다. 대소문자는 구분하지 않는다.
10.5 퀴즈
정답은 d이다. 문자열은 큰따옴표로 감싸야 한다.
정답은 c이다.
정답은 e이다. ull은 unsigned long long 이다.
정답은 c이다. 접미사가 붙어있지 않으면 double이다.
10.6 연습문제 : 리터럴 사용하기
정답은 다음과 같다.
'e', "world!", 8, 4.9e-302L
10.7 연습문제 : 상수 사용하기
정답은 다음과 같다.
- unsigned long long int con1 = 10ULL;
- float con2 = 3.2f
- char con3 = 't';
10.8 심사문제 : 리터럴 사용하기
정답은 다음과 같다.
076, -2147483647LL, 4.528172L
10.9 심사문제 : 상수 사용하기
정답은 다음과 같다.
long double con1 = -2.225074e-308
Unit 11. 입력값을 변수에 저장하기
C를 공부할 때는 콘솔에 글자를 입출력 하는데, 콘솔에 입력하는 방식을 표준 입력(standard input, stdin), 출력하는 방식을 표준 출력(standard output, stdout)이라고 한다.
11.1 정수 입력 받기
scanf 함수를 사용하여 표준 입력으로 사용자의 입력을 받아온다. scanf함수는 다음과 같이사용한다.
- scanf(서식, 변수의주소);
- int scanf(char const * const _Format, ...);
- 성공하면 가져온 값의 개수를 반환, 실패하면 EOF(-1)를 반환
파이썬에서는 input함수로 입력받으면 모두 문자열 이였는데, C에서는 입력값을 저장할 변수를 미리 만들어 두고, 그 변수에 입력값을 저장하기 때문에 입력받을 값의 자료형이 정해져 있다.
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
int main()
{
int num1;
printf("정수를 입력하세요 : ");
scanf("%d", &num1);
printf("%d\n", num1);
return 0;
}
scanf함수의 첫번째 인수로는 큰따옴표 안에 서식지정자를 넣어 입력받을 값의 형태를 설정한다. 두번째 인수에는 입력값을 저장할 변수를 넣는데, 변수 앞에 &를 붙여야 한다. 맨 첫 줄은 윈도우 Visual studio에서 발생하는 에러를 방지하는 것으로 입력값의 길이를 설정할 수 없어서 보안에 취약하니 사용하지 말라는 경고가 출력될수 있으니 방지하는 것이다. 첫줄을 사용하지 않아도 에러가 발생하지 않으려면 visual studio전용 함수인 입력값 길이를 저장할 수 있는 함수인 scanf_s 함수가 있다.
11.2 한 번에 정수 두 개 입력받기
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
int main()
{
int num1, num2;
printf("정수를 입력하세요 : ");
scanf("%d %d", &num1, &num2);
printf("%d %d\n", num1, num2);
return 0;
}
입력값 두개 이상을 받을 때는 입력값의 개수 만큼 서식지정자를 지정하고, 서식지정자 개수만큼 입력받을 변수를 넣어주면 된다. 입력 받을 때도 입력값은 공백(스페이스)로 구분한다.
11.3 실수 입력받기
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
int main()
{
float num1;
printf("실수를 입력하세요 : ");
scanf("%f", &num1);
printf("%f\n", num1);
return 0;
}
실수를 입력받았기 때문에 1을 입력해도 1.0이 출력된다.
실수를 입력받을 것이므로 변수를 float로 선언하고, 서식지정자를 %f를 사용한다.
만약 double로 선언했으면 scanf의 서식지정자로는 %lf를 사용해야 하며, long double로 선언했으면 %Lf를 사용해야 한다.
입력받고자 하는 자료형에 맞게 변수를 선언하고, 변수에 맞는 서식지정자를 사용하면 된다.
11.4 문자 입력받기
#define _CRT_SECURE_NO_WARNINGS // scanf 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
int main()
{
char c1;
printf("문자를 입력하세요 : ");
scanf("%c", &c1);
printf("%c\n", c1);
return 0;
}
문자를 입력받을 것이므로 변수는 char로 선언하고, 서식지정자도 %c를 사용하면 된다.
다음과 같이 getchar 함수를 이용해서 문자를 입력받을 수도 있다.
#include <stdio.h>
int main()
{
char c1 = getchar();
printf("%c\n", c1);
return 0;
}
getchar 함수는 문자 하나를 입력받아 결과를 반환하는 함수이다. 문자를 여러개 입력받아도 첫번째 문자 하나만 반환된다.
이와 대응되는 함수로는 문자 하나를 화면에 출력하는 putchar함수가 있다.
#include <stdio.h>
int main()
{
char c1 = getchar();
putchar(c1);
return 0;
}
11.5 퀴즈
정답은 b이다.
정답은 e이다.
정답은 c이다.
11.6 연습문제 : 한 번에 정수 세 개 입력받기
정답은 다음과 같다.
"%d %d %d", &num1, &num2, &num3
11.7 심사문제 : 정수, 실수, 문자 입력받기
정답은 다음 코드와 같다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int n;
float f;
char c;
scanf("%d %f %c", &n, &f, &c);
printf("%d\n%f\n%c\n", n, f, c);
return 0;
}
Unit 12. 덧셈 뺄셈 하기
12.1 덧셈, 뺄셈 하기
덧셈은 +연산자, 뺄셈은 -연산자를 사용한다.
#include <stdio.h>
int main()
{
int num1, num2;
num1 = 1 + 1;
num2 = 1 - 2;
printf("%d\n", num1);
printf("%d\n", num2);
return 0;
}
num1 에 1+1을 저장하고, num2에 1-2를 저장하고 각 변수를 출력하면 각각의 연산결과가 나오는 것을 확인할 수 있다.
다음과 같이 실수에서도 덧셈, 뺄셈의 연산은 동일하다.
#include <stdio.h>
int main()
{
float num1, num2;
num1 = 1.0f + 0.112233f;
num2 = 1.0f - 0.123456f;
printf("%f\n", num1);
printf("%f\n", num2);
return 0;
}
12.2 변수 하나에서 값을 더하거나 빼기
다음과 같이 변수 하나에서 값을 더하거나 뺄 수 있다.
#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에 기존 num1의 값에서 2를 더한 값을 저장하는 것이다. num1 + 2 가 처리되어 3이 된것이 num1에 다시 저장되는 것이다. 뺄셈의 경우도 동일하다.
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의 축약형이고, num2의 경우 뺄셈 연산도 마찬가지다.
12.3 퀴즈
정답은 b이다.
정답은 c이다.
정답은 d이다.
12.4 연습문제 : 덧셈, 뺄셈 하기
num1의 값은 현재 5이므로 답은 95이다.
12.5 : 심사문제 : 덧셈, 뺄셈하기
출력하는 값이 num3이므로 연산한 값은 num3에 저장해야 한다.
num3 = num1 + num2 - 4.5f;
Unit 13. 증가, 감소 연산자 사용하기
C에서는 값을 1 증가시키는 ++연산자와 값을 1 감소시키는 -- 연산자를 제공한다. 정수에서는 1을 증가와 감소 시키지만, 포인터 연산을 하게 되면 자료형의 크기만큼 증가, 감소 시킨다.
13.1 변수의 값을 1 증가, 감소 시키기
증가연산은 ++연산자를 사용하고, 감소연산은 --연산자를 사용하며 값을 1 증가시키거나 감소시킨다. 증가, 감소 연산자는 다음과 같이 변수의 앞이나 뒤에 붙일 수 있다.
#include <stdio.h>
int main()
{
int num1 = 1, num2 = 1;
num1++;
--num2;
printf("num1 : %d\n", num1);
printf("num2 : %d\n", num2);
return 0;
}
num1++ 를 풀어서 쓰면 num1 = num1 + 1과 같고, num1+=1 과도 동일하다. 감소 연산자도 마찬가지다.
13.2 실수 자료형에 증감 연산자 사용하기
실수자리에 증감 연산자를 사용하면 다음과 같다.
#include <stdio.h>
int main()
{
float num1 = 2.1f;
float num2 = 2.1f;
num1++;
num2--;
printf("%f %f\n", num1, num2);
return 0;
}
실수에서도 증감연산자를 사용하여 1 증가시키거나 감소시킬수 있다. 증감연산자는 정수 부분에만 영향을 미치며, 소수점 이하 자리에는 영향을 미치지 않는다.
13.3 문자 자료형에 증감 연산자 사용하기
문자 자료형에 증감 연산자를 사용하면 다음과 같다.
#include <stdio.h>
int main()
{
char c1 = 'b';
char c2 = 'b';
c1++;
c2--;
printf("%c %c\n", c1, c2);
return 0;
}
문자 자료형도 실제로는 정수이기 때문에 아스키 코드값이 1 증가하거나 감소하여 b에서 1을 증가시키면 c가되고, 1을 감소시키면 a가 된다.
파이썬에서는 문자 자료형에 숫자를 연산하면 에러가 발생한다.
13.4 증감 연산자의 위치에 따른 차이점 알아보기
증감 연산자는 변수 앞이나 뒤에 사용할 수 있다. 이는 증감연산자 단독으로 사용했을때는 차이가 없지만, 연산자를 사용한 뒤 다른 변수에 할당할 때 위치에 따라 차이가 발생한다.
다음은 증감연산자를 변수 뒤에 사용했을 경우이다.
#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과 num4에 처음 num1과 num2에 저장한 2가 저장되어 있다. 위 연산을 풀어서 쓰면 다음과 같다.
num3 = num1;
num1 = num1 + 1;
num4 = num2;
num2 = num2 - 1;
이와 같이 증감 연산자를 변수 뒤에 사용하는 것을 후위 연산이라고 하며 다른 변수에 할당할 때는 현재 변수의 값을 다른 변수에 할당한 후 증감연산자가 수행되어 변수의 값이 1 증가, 감소 된다. 따라서 num3과 num4에는 num1과 num2의 처음 값인 2가 저장되고 이후 증감 연산이 수행되어 num1과 num2에는 각각 3과 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;
}
위 연산을 풀어서 작성하면 다음과 같다.
num1 = num1 + 1;
num3 = num1;
num2 = num2 - 1;
num4 = num2;
증감 연산자를 변수 앞에 사용한 것을 전위 연산이라고 한다. 전위 연산은 할당 전에 연산을 하여 연산한 값을 변수에 할당한다. num1 + 1을 한 값이 num3에 저장되어 3이 출력되는 것이다. 감소 연산도 동일하다.
변수에 할당하지 않고 함수의 인수로 사용했을 때도 동작 방식은 같다.
#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;
}
#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;
}
변수 뒤에 증감연산자를 사용하면(후위 연산) 기존 값이 먼저 출력되고 이후 증감 연산을 진행한다. 또한 변수 앞에 증감연산자를 사용하면(전위 연산) 연산을 먼저 하고, 연산한 값을 출력한다.
13.5 퀴즈
정답은 d이다.
정답은 c이다.
정답은 e이다.
후위 연산 이기 때문에 정답은 12 이다.
전위연산이기 때문에 정답은 8이다.
13.6 연습문제 : 증가, 감소 연산자 사용하기
num3은 num1의 처음 값에서 1증가시키고, 1감소시킨 것이기 때문에 첫번째 답은 2이고, num4는 num2의 처음값을 1 감소시키고 그 값을 후위연산한 것을 저장했기 때문에 두번째 답은 8 이다.
13.7 심사문제 : 증가, 감소 연산자 사용하기
정답은 다음 코드와 같다.
num1++;
num2++;
c1--;
Unit 14. 곱셈, 나눗셈 하기
14.1 곱셈, 나눗셈 하기
곱셈은 *연산자, 나눗셈은 / 연산자를 사용한다.
#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으로 나누려고 하면 컴파일 에러가 발생하고, 변수에 다른 숫자와 0을 각각 저장해서 나누면 컴파일 에러는 발생하지 않지만 실행했을 때 에러를 발생한다.
다음은 실수를 계산한 것이다.
#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가 나온다. 실수의 계산은 경우에 따라 오차가 발생하기도 한다. 곱셈 뿐아니라 덧셈, 뺄셈, 나눗셈 등에서도 발생할 수 있다.
실수도 코드에서 0으로 직접 나누면 컴파일 에러가 발생한다.
다음과 같이 변수에 0.0을 저장하여 나누면 정수처럼 실행했을 때 에러가 발생하지 않고, inf(무한대)가 나온다.
#include <stdio.h>
int main()
{
float num1 = 1.0f;
float num2 = 0.0f;
float num3;
num3 = num1 / num2;
printf("%f\n", num3);
return 0;
}
14.2 변수 하나에서 값을 곱하거나 나누기
#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;
}
위 코드는 변수의 값을 곱하거나 나눈뒤 다시 그 변수에 저장하여 계산 결과를 같은 변수에 유지시킨 것이다.
곱셈후 할당 *=, 나눗셈 후 할당 /= 연산자를 사용하여 위 코드의 연산을 다음과 같이 축약할 수 있다.
num1 *= 3;
num2 /= 2;
14.3 퀴즈
정답은 a 이다.
정답은 c이다. 0으로 나누면 컴파일 에러가 발생한다.
정답은 c이다.
14.4 연습문제 : 삼각형의 넓이 구하기
삼각형의 넓이는 밑변 * 높이 / 2 이므로 정답은 다음과 같다.
base * height / 2
14.5 : 심사문제 : 원의 넓이 구하기
원의 넓이는 반지름 * 반지름 * 원주율 이므로 정답은 다음 코드와 같다.
radius = diameter / 2;
area = radius * radius * M_PI;
'Project H4C Study Group' 카테고리의 다른 글
[Project H4C] C언어 코딩도장(4) (0) | 2021.02.19 |
---|---|
[Project H4C] C언어 코딩도장(3) (0) | 2021.02.18 |
[Project H4C] C언어 코딩도장(1) (0) | 2021.02.16 |
[Project H4C] opentutorials HTML(6) (0) | 2021.02.12 |
[Project H4C] opentutorials HTML(5) (0) | 2021.02.12 |