2. 변수, 자료형, 연산자
1. Intro
프로그램의 3단계 - 입력, 처리, 출력 - 과정의 입력과 출력 부분을 지난 단원에서 다루었다. 앞으로의 내용은 모두 정보의 처리 과정과 관련된 것들을 주로 다룰 것이다. 정보를 처리하는 과정에 있어 정보를 담는 그릇인 변수, 변수에 담긴 정보의 종류에 대한 정보인 자료형, 그리고 정보를 가공하는데 필요한 연산자들을 알고 적절히 사용하는 것은 매우 중요하다.
2. 변수와 자료형
변수는 자료를 저장하는 저장 공간으로, 주기억장치의 메모리의 일부를 사용한다. 변수를 사용하는 과정은 다음과 같다.
1. 변수 선언 2. 변수 값 설정 3. 변수를 목적에 맞게 사용
다음 예시를 살펴보자.
#include <stdio.h>
int main()
{
int a; // [1]
a = 10; // [2]
printf("%d", a); // [3]
return 0;
}
위 코드는 정수형 변수를 하나 선언한 후 변수에 숫자 10을 대입하고, 그것을 출력하는 간단한 코드이다.
[1]번째 줄이 변수를 선언한 부분이다. 변수를 선언할 때애는 다음의 형식을 따른다.
int a;
[변수의 자료형] [변수의 이름] ;[세미콜론]
변수의 자료형이란 변수가 정수형 변수인지, 실수형 변수인지, 문자형 변수인지를 나타내는 것이다. 자료형의 종류는 상당히 많은데, 가장 많이 쓰이는 종류는 다음과 같다.
int a; // 정수형 변수, 4 byte
long long b; // 정수형 변수, 8 byte
float c; // 실수형 변수, 4 byte
double d; // 실수형 변수, 8 byte
char e; // 정수형(문자형) 변수, 1 byte
[1]. 정수형 변수 : 정수형 변수는 정수값을 저장하는 변수이다. 0, 1, 10, -10 등의 정수값을 저장할 수 있다. int, long long 등이 있다.
[2]. 실수형 변수 : 실수형 변수는 실수값을 저장하는 변수이다. 1.0, 3.14, 2.818등의 실수값을 저장한다. float, double 등이 있다.
[3]. 정수형(문자형) 변수 : char은 a, b, X와 같은 문자를 저장하는 변수이다. 문자를 저장할 때 실제로는 ASCII 코드 값으로 저장되기 때문에 이를 정수형 변수로 취급할 수 있다.
각 자료형의 변수를 선언할 때, 주기억장치의 메모리에 일정 공간을 할당받는다. 공간의 크기는 위에서 언급한 것 처럼 int형은 4바이트, double형은 8바이트 등으로 일반적으로 자료형마다 따로 정해져 있다. 공간의 크기는 변수가 담을 수 있는 최저, 최대 정보의 크기와 깊은 연관이 있다.
우선, 1바이트는 8개의 비트로 이루어져있다. 1개의 비트는 0 또는 1의 값을 가질 수 있다.
1 bit가 0 또는 1, 즉 2개의 값을 가질 수 있으므로 1 byte는 2^8 = 256개의 값을 저장할 수 있다. 이진수 0000 0000이 0이고 1111 1111이 255임을 통해 직관적으로 이해할 수 있다.
int 형 변수는 4 byte의 공간을 할당받고 이는 2^(8*4) = 2^32 개의 값을 저장할 수 있는 공간이다.
이때 공간의 맨 첫번째 비트는 부호비트로, 음수와 양수를 구별하는데 사용된다. 그렇기 때문에 실제로 표현할 수 있는 범위는
0~2^(32-1)-1, -1~-2^(32-1)이고 둘을 합치면 -2147483648 ~ 2147483647이다. 이 범위를 넘어가는 값은 보다 많은 공간을 쓸 수 있는 자료형인 long long을 쓰거나, 양의 정수에 한해 부호 없는 4 byte 정수형 자료형인 unsigned int를 사용하여 표현할 수 있다.
지금까지의 내용을 정리하면 다음과 같다.
1. 변수는 자료를 담는 그릇이다.
2. 변수에 담을 자료의 종류와 변수의 자료형이 일치하여야 한다.
3. 자료형은 각각 크기가 한정되어 있으며 표현할 수 있는 값의 범위가 존재한다.
2. 연산자
연산자는 수학에서의 +, -, *, /과 같은 연산 기호를 의미한다. 크게 산술 연산자, 대입 연산자, 관계 연산자, 비트 연산자로 나눌 수 있다.
[1]. 대입 연산자 [=]
연산자 [=] 은 '연산자 오른쪽의 값을 왼쪽의 변수에 대입한다'는 의미를 가진다. 위 예시의 [2]번째 줄은 다음 의미를 가진다.
a = 10; // 변수 a에 10이라는 값을 대입한다.
수학에서의 [=]은 좌변과 우변이 같다는 의미로 사용되지만, 대부분의 프로그래밍 언어에서는 대입의 의미를 갖는다. '같다'라는 의미의 연산자는 [==]임에 주의하여야 한다.
[2]. 산술 연산자 [+, -, *, /, %]
산술 연산자는 크게 5가지가 있으며 그 종류는 다음과 같다.
연산자 |
의미 |
사용 예시 | 결과 |
+ |
덧셈 |
a = 2 + 5; | a == 7 |
- |
뺄셈 |
a = 2 - 5; | a == -3 |
* |
곱셈 |
a = 2 * 5; | a == 10 |
/ |
나눗셈(몫) |
a = 2 / 5; | a == 0 (a 는 int형 변수) |
% |
나눗셈(나머지) |
a = 2 % 5; | a == 2 |
간단한 사칙연산은 수학에서의 그것과 크게 차이가 없다. 다만 %라는 나머지 연산이 존재함을 눈여겨 보아야 한다.
[2]*. 특수한 경우의 산술 연산자 [++, --, +=, *=, -=, /=, %=]
개발을 하다 보면 어떤 변수에 반복적인 연산을 할 때가 종종 있다. 개수를 세거나, 배수를 구하거나, 홀수만 출력해야 하는 경우가 바로 그것이다. 이를 보다 간단하고 직관적으로 표현할 수 있도록 하는 특수한 산술 연산자가 있다. 증감 연산자와 복합 대입 연산자가 그것이다.
1. 증감 연산자
증감 연산자는 ++, --가 있고, 이들은 각각 값을 1씩 더해주거나 빼주는 역할을 한다.
다음 예시를 살펴보자.
#include <stdio.h>
int main()
{
int a;
a = 10;
printf("%d ", a++); // [1]
printf("%d ", ++a); // [2]
printf("%d ", a--); // [3]
printf("%d ", --a); // [4]
return 0;
}
이 코드의 실행 결과부터 보면 10 12 12 10일 것이다. 11 12 11 10이 아님에 유의하라. 왜 그런지 살펴보자.
[변수]++ 나 [변수]--처럼 변수 이름 뒤에 붙는 증감연산자를 후치증가연산자, 후치감소연산자라 부른다. 이 연산자의 특징은, 해당 줄의 동작이 끝난 후에 변수를 증가시키거나 감소시킨다는 점이다.
[1]번 줄을 살펴보면 a++의 후치증가연산자가 사용된 것을 볼 수 있다. 우선 변수의 값 10이 먼저 출력이 된 후에 연산자가 작용하여 a의 값이 1이 증가 된 11이 되는 것이다.
++[변수]나 --[변수]처럼 변수 이름 앞에 붙는 증감연산자를 전치증가연산자, 전치감소연산자라 부른다. 이들의 특징은, 해당 줄의 동작이 시작하기 전에 변수의 값을 증가시키거나 감소시킨다는 점이다.
[2]번 줄을 살펴보면 ++a의 전치증가연산자가 사용된 것을 볼 수 있다. printf 함수를 실행하기 전 a의 값을 1 증가시킨다. 그 다음 printf 함수를 실행하기 때문에 결과적으로 12가 출력되는 것이다.
[3]번줄과 [4]번줄이 각각 후치감소연산자와 전치감소연산자를 사용했기 때문에 11 10이 아닌 12 10이 출력됨을 알 수 있다.
2. 복합대입연산자
어떤 정수형 변수 a에 값 10을 대입하고 그것을 2배 하는 코드를 작성해보자.
#include <stdio.h>
int main()
{
int a;
a = 10;
a = a*2;
return 0;
}
복합대입연산자란 대입 연산자와 산술 연산자가 같이 쓰인 경우이다. a = a*2;와 같은 경우이다. 이를 다음과 같이 간단하게 쓸 수 있다.
a *= 2;
즉, 대입연산자와 산술 연산자가 같이 쓰일 경우 다음과 같이 간단하게 표현할 수 있다.
a = a * 2; [변수] [대입연산자] [변수] [산술 연산자] [피연산자]
a *= 2; [변수] [산술연산자][대입연산자] [피연산자]
이를 다른 산술 연산자에 대해 정리하면 다음과 같다.
연산자 |
다른 표현법 |
결과 |
a = a + b; |
a += b; |
a에 a와 b를 더한 값이 저장된다. |
a = a - b; |
a -= b; |
a에 a에서 b를 뺀 값이 저장된다. |
a = a * b; |
a *= b; |
a에 a와 b를 곱한 값이 저장된다. |
a = a / b; |
a /= b; |
a에 a를 b로 나눈 몫이 저장된다. |
a = a % b; |
a %= b; |
a에 a를 b로 나눈 나머지가 저장된다. |
[3]. 관계연산자 [<, >, <=, >=, ==, !=]
관계연산자는 피연산자들끼리의 대소, 동일과 같은 관계를 비교하는 연산자이다. 그 의미는 다음과 같다.
연산자 |
의미 |
< |
좌변이 우변보다 작은지를 비교 |
> |
좌변이 우변보다 큰지를 비교 |
<= |
좌변이 우변보다 작거나 같은지를 비교 |
>= |
좌변이 우변보다 크거나 같은지를 비교 |
== |
좌변과 우변이 같은지를 비교 |
!= |
좌변과 우변이 다른지를 비교 |
이 연산자는 뒤에서 다룰 조건문을 사용할 때 매우 많이 쓰이므로 익숙해지는 것이 좋다.
[4]. 비트연산자 [&, |, ^, ~, >>, <<]
비트 연산자는 피연산자를 비트단위로 연산하는 연산자이다. 초급 단계에서 많이 쓸 일은 없지만 잘 쓰면 코드를 간결하게 만들 수 있으며 신비한 마법같은 코드를 구현할 수도 있다.
비트연산자의 설명은 다음과 같다.
연산자 |
설명 |
& |
피연산자의 AND 연산 |
| |
피연산자의 OR 연산 |
^ |
피연산자의 XOR 연산 |
~ |
피연산자의 NOT 연산 |
>> |
피연산자의 비트를 오른쪽으로 이동 |
<< |
피연산자의 비트를 왼쪽으로 이동 |
[&] AND 연산
AND 연산은 논리곱이라고도 하며, 둘의 비트가 모두 1일 때만 1을 반환하는 연산이다. 진리표는 아래와 같다.
피연산자 A |
피연산자 B |
결과값 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
둘 다 1일때만 1을 반환하기 때문에 둘을 곱한것과 결과가 같다고 해서 논리곱이라 부른다.
[|] OR 연산
OR 연산은 논리합이라고도 하며, 둘의 비트 중 하나라도 1이면 1을 반환하는 연산이다. 진리표는 아래와 같다.
피연산자 A |
피연산자 B |
결과값 |
1 |
1 |
1 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
0 |
둘 중 하나라도 1이면 1을 반환하기 때문에 둘을 합한 것과 결과가 같다고 하여 논리합이라 부른다.
[^] XOR 연산
XOR 연산은 배타적 논리합이라고도 하며, 둘의 비트가 서로 다를 때 1을 반환한다. 진리표는 아래와 같다.
피연산자 A |
피연산자 B |
결과값 |
1 |
1 |
0 |
1 |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
0 |
[~] 비트 반전 연산
~ 연산은 비트의 부호를 반전하는 연산이다. 보수 연산에서 사용된다.
피연산자 |
결과값 |
1 |
0 |
0 |
1 |
[<<, >>] Shift 연산
shift 연산은 주어진 수 만큼 비트를 이동시키는 연산이다. << 의 경우 비트를 왼쪽으로, >>의 경우 비트를 오른쪽으로 이동시킨다.
예를 들어 5 << 2의 경우
위 그림처럼 비트가 이동하고 나머지 비트는 0으로 채워진다. 결과적으로 4가 곱해진 것을 볼 수 있는데, a << b의 결과는 a*2^b임을 알 수 있다. 같은 맥락으로, a >> b의 결과는 a/b^2임을 알 수 있다.
문제 1. 두 개의 정수를 입력받아 더한 값, 뺀 값, 곱한 값, 나눈 몫, 나눈 나머지를 출력하는 코드를 작성하시오.
답안 예시
#include <stdio.h>
int main()
{
int a, b;
scanf("%d %d", &a, &b);
printf("%d %d %d %d %d", a+b, a-b, a*b, a/b, a%b);
return 0;
}
'Programming Language > basic C Language' 카테고리의 다른 글
4. 제어문 - if, else if, else, switch~case (0) | 2018.10.06 |
---|---|
3. 배열, 반복문 (while, for, do~while) (0) | 2018.10.06 |
1. 표준입출력 (0) | 2018.10.06 |
0. 개발 환경 구축하기 (0) | 2018.10.06 |
CodeHighlightingTest (0) | 2018.10.06 |