혼자 공부하는 C - 변수와 연산자




프로그래밍 언어의 기본적인 문법인 변수와 연산 종류에 대해 정리합니다.

기본 문법이므로 조금 딱딱할 수 있습니다.


변수

변수 선언 방법

  • 변수명은 메모리에 붙이는 임시 주소와 같습니다.
  • 변수를 선언하면 메모리에 저장 공간이 생깁니다.
    • 처음 값은 알 수 없다. 컴퓨터 메모리는 재활용되기 때문.
    • 프로그램이 종료되면 메모리 공간을 반납하고 새 프로그램이 씁니다.
    • 새 프로그램에서 이 값은 의미가 없습니다. 따라서, 쓰레기 값 (garbage value)이라 합니다.
    • 이 값이 문제가 될 수 있으므로, 원하는 값으로의 초기화 반드시 필요합니다.

1
a = 10;

변수 선언과 대입 규칙은 기본적인 프로그래밍 규칙을 알려주므로 생략합합니다.



정수 자료형

  • char : 1바이트.
    • -128~127 의 값을 저장할 수 있고, 보통 문자를 저장하는 용도.
  • short : 2바이트
  • int: 4바이트
  • long: 4바이트
  • long long: 8바이트

데이터 크기에 적절한 자료형을 사용하면 됩니다. 몇 가지 선택방법이 있습니다.

  1. 특별한 경우가 아니면 정수형은 int를 사용합니다.
  2. long 형은 큰 값을 저장할 때 사용합니다.



unsigned 정수 자료형

  • 정수형은 양수, 음수를 모두 저장하지만, 양수만 저장하면 두배 더 넓은 범위를 저장할 수 있습니다.
    • 예) 나이와 같이 음수일 수 없는 데이터는 unsigned를 사용.



실수 자료형

  • float : 4바이트, 유효숫자 7
  • double : 8바이트, 유효숫자 15
  • long double : 8바이트 이상, 유효숫자 15 이상.

예를 들어 보겠습니다.


1
2
3
4
5
6
7
8
9
float ft = 1.234567890123456789;
double db = 1.234567890123456789;

printf("float형 변수의 값: %.20f\n", ft);
printf("double형 변수의 값: %.20lf\n", db);


/*float형 변수의 값: 1.23456788063049316406
double형 변수의 값: 1.23456789012345669043*/

float과 doube을 같게 지정하였으나 값이 초기값과 다르게 나타납니다.

오차가 발생할 수 있으므로, float은 7자리, double은 15자리 내 범위만 사용이 권장됩니다.

유효 숫자의 개수가 걱정이라면 아래 2가지 방법을 고려해 볼 수 있습니다.

  1. 정수형을 기본으로 사용하고 필요한 경우에만 실수형을 사용.
  2. 실수형은 유효숫자가 많은 double 형을 기본으로 사용.

문자열 저장

하나의 문자가 아닌 여러 문자를 저장할 때에는 배열 (array)을 사용합니다.


1
char 배열명[문자열길이+1] = 문자열;

문자열 길이 +1 만큼 지정해줘야 하는 이유
→ 컴파일러가 문자열 끝에 null character인 \0 를 입력하기 때문. 추후 12장 설명.

배열의 길이가 문자열보다 길어도, 문자열의 끝에 Null 문자가 있으므로, 출력은 거기까지만 합니다.


const를 사용한 변수

const는 변수와 달리 초기화된 값을 바꿀 수 없습니다.

→ 값이 바뀌지 않는 것을 보장할 수 있습니다.


예약어와 식별자

  • 예약어 (reserved word; key word): 컴파일러와 사용 방법이 약속된 단어.
  • 식별자 (identifier): 필요에 따라 만들어 사용하는 단어.



데이터 입력

scanf 함수 사용법

scanf는 scan formatted로 input을 변환 문자에 따른 타입으로 바꾸어 저장합니다.

(printf와 거의 같습니다.)


1
scanf("%d", &a); // 1번째는 변환문자, 2번째는 변수명과 그 앞에 &룰 붙인다.

& 는 앰퍼샌드 (ampersand)라고 한다.

변수의 주소를 구하는 연산자로 9장 포인터에서 자세히 다룬다.


아래처럼 동시에 여러 값을 받을 수도 있습니다.


1
scanf("%d%lf", &a, &b); // int a와 double b를 한번에 받는다.

문자와 문자열 입력

문자열은 char 배열에 %s를 사용해 입력하는데, 변수에 &를 붙이지 않는다.⭐

또한 공백 없이 나란히 입력해야한다.

중간 확인

그러면 문제 몇가지를 풀어서 확인을 해보겠습니다.


1. 아래 변수를 이용한 scanf 사용법 중 맞은 것 골라보기.

1
2
3
4
5
char ch;
short sh;
int in;
float ft;
double db;

1️⃣ scanf("%d", &ch);
2️⃣ scanf("%d", &sh);
3️⃣ scanf("%d%f", &in, &ft);
4️⃣ scanf("%f", &db);


2. 다음 빈칸 채워보기

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

int main(void)
{
char fruit[20];
int cnt;

printf("좋아하는 과일 : " );
scanf("%s", /* 1️⃣ */);
printf("몇 개 : ");
scanf("%d", /* 2️⃣ */);
printf("%s를 %d개 드립니다.", fruit, cnt);

return 0;
}

실행결과

1
2
3
좋아하는 과일 : 망고
몇 개 : 3
망고를 3개 드립니다.

3. 실행예시를 보고 코드를 작성해보기

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int main(void)
{
char ch;
printf("문자 입력: ");
// INPUT area

return 0;
}

실행 결과 1.

1
2
문자 입력: A
A문자의 아스키코드 값은 65입니다.

실행 결과 2.

1
2
문자 입력: t
t문자의 아스키코드 값은 116입니다.





정답

1번

3️⃣


2번

1️⃣ fruit
2️⃣ &cnt


3번

1
2
scanf("%c", &ch);
printf("%c문자의 아스키코드 값은 %d입니다.\n", ch, ch);



연산자

1. 산술 연산자, 관계 연산자, 논리 연산자

  • 연산자, 피연산자 구분.
  • 보통은 기능에 따라 분류하지만, 피연산자의 개수에 따라 나눌 수도 있다.
    • 단항 연산자: - 3
    • 이항 연산자: 3 + 5
    • 삼항 연산자: (3 < 5) ? 1 : 0

산술 연산자와 대입 연산자

  • 더하기 : +
  • 빼기: -
  • 곱하기 : *
  • 나누기 : /
  • 나머지 : %

증감 연산자

1씩 더하고 빼는 연산이 아래처럼 가능.

1
2
++a; // a에 1을 inplace로 더한다
--a; // a에 1을 inplace로 뺀다

전위 표기와 후위 표기

증감 연산자의 위치에 따라 전위 (prefix) 혹은 후위 (postfix) 로 구분된다.

  • prefix : ++a → 값이 증감하고 나서, 연산에 사용한다.
  • postfix : a++ → 연산에 사용하고 나서, 증감한다.

(++a) + a + (++a) 의 결과는?

같은 변수를 두번 이상 사용할 때, 증감 연산자를 사용하면 안된다.
이는 C언어 표준에 정의되어 있지 않으므로, 컴파일러마다 결과가 다르다.
따라서 정답이 없으므로 이런 코드를 사용해선 안된다.

관계 연산자

  • , <, == , != 을 사용.

  • 결과 값은 1과 0 으로 나온다 (True, False)

논리 연산자

  • && → AND
  • || → OR
  • ! → NOT
숏 서킷 룰 (short circuit rule)
좌항 만으로 연산 결과를 판별하는 기능. && 와 || 는 숏 서킷 룰이 적용된다.

예) False && True 라면, 이미 False가 좌항에 있으므로, 우항을 살펴보지 않는다.

예) True || False 라면, 이미 True가 좌항에 있으므로, 우항을 살펴보지 않는다.


연산의 결과값을 처리하는 방법

변수에 저장하지 않으면 값은 버려진다는 말.

a + b;를 하면 결과는 버려지고, res = a + b; 이런 식으로 써야한다는 내용.


형 변환 연산자

1
2
3
4
// (자료형) 피연산자

int a = 10;
(double) a;

자동 형 변환

피연산자 (변수) 2개의 연산이라면, 두 피연산자의 데이터 타입은 같아야한다.

다르다면 자동으로 일치시키는 자동 형 변환 과정을 수행한다.

일반적인 규칙은, 크기가 작은 값의 타입이 크기가 큰 값의 타입으로 바뀐다.

정수(4바이트), 실수(8바이트)를 연산하면 정수가 실수로 바뀐다.


sizeof 연산자

피연산자의 크기를 바이트 단위로 계산하여 알려준다.


1
2
sizeof(int); // int형의 크기를 구할 때
sizeof(10); // 상수의 크기를 구할 때

복합대입 연산자

연산의 결과를 바로 변수에 저장하는 연산.

  • +=
  • -=
  • *=
  • /=
  • %=

콤마 연산자

여러개의 수식을 차례로 나열해야 할 때 사용한다.

오른쪽의 피연산자가 최종 결과값이 된다.


1
2
3
4
int a = 10, b = 20;
int res;
res = (++a, ++b); // a는 11, b는 21이 되고, res에 21이 대입됨.
res = ++a, ++b; // a는 12, b는 22가 되고, res는 12가 대입됨.

추후 제어문에서 조건식을 나열하는 괄호 안과 같이 세미콜론 사용이 불가능한 구조에서 사용한다. 예) for 루프


조건 연산자

유일한 삼항 연산자.


1
(a > b) ? a : b; //조건식 ? True 값 : False 값; 으로 사용한다.

조건 연산자에서 피연산자에 대입식 사용하기


아래 라인을

1
res = (a > b) ? a : b;

아래처럼 바꿀 수 있다. 결과는 같다.

1
(a > b) ? (res = a) : (res = b);

비트 연산자

  • 논리 연산 → &, |, ^

  • 비트 이동 연산 → >>, <<

  • & : 비트별 논리곱 연산자
    01010 10
    01100 12
    01000 10 & 12 == 8

  • ^ : 비트별 배타적 논리합 연산자
    01010 10
    01100 12
    00110 10 ^ 12 == 6

  • | : 비트별 논리합 연산자
    01010 10
    01100 12
    01110 10 & 12 == 14

  • | : 비트별 부정 연산자
    01010 10
    10101 ~10 == -11

  • 비트 쉬프트 (left 는 오른쪽에 0을 추가하여 모두 왼쪽으로 개수만큼 이동)
    01010 10
    10100 10 << 1 == 20

  • 비트 쉬프트 (right는 왼쪽에 0을 추가하여 모두 오른쪽으로 개수만큼 이동)
    01010 10
    00010 10 >> 2 == 2


중간 확인

그러면 문제 몇가지를 풀어서 확인을 해보겠습니다.

1. short와 long의 자료형 크기를 비교하여 출력하는 코드 작성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

int main(void)
{
int res;

// 1️⃣
// sizeof의 피연산자로 자료형 이름을 사용해 크기를 바이트 단위로 계산
// short형의 크기가 long형보다 크면 참이므로 , 그렇지 않으면 0을 res에 저장

// 2️⃣
// res가 1 과 같으면 short형의 크기가 크므로 출력하고 그렇지 않으면 long을 출력한다.

return 0;
}

2. 야구장 경기장 좌석수가 70개고 입장객수가 65명일 때 입장률을 표시하는 코드 작성

1
2
3
4
5
6
7
8
9
#include <stdio.h>

int main(void)
{
// inpui area
// seats, audience, rate로 변수를 지정하고 비율을 소수점 1개로 출력해보자.

return 0;
}

3. 3.76시간이 몇 시, 몇 분, 몇 초인지 출력하는 코드 작성

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main(void)
{
int hour, min, sec;
double time = 3.76;

//input area


return 0;
}

실행결과

1
3.76시간은 3시간 4535초입니다.

도전문제

체중 (kg), 키(cm)를 입력하면 BMI를 계산하여 체중관리 조언을 하는 프로그램 작성.

  • BMI가 20이상 25미만이면 “표준입니다” 출력.
  • 그 외에는 “체중 관리가 필요합니다” 출력
  • BMI: 몸무게 / (키의 제곱)

실행 결과

1
2
몸무게(kg)와 키(cm) 입력 : 66 185.6
체중관리가 필요합니다





정답

1번

1️⃣ res = sizeof (short) > sizeof (long);
2️⃣ printf("%s\n", (res==1) ? "short" : "long");


2번

1
2
3
4
5
int seats = 70;
int audience = 65;
double rate;
rate = (double) audience / (double) seats * 100.0;
printf("입장률 : %.1f%%\n", rate);

3번

1
2
3
4
5
6
7
8
hour = (int) time;
time -= hour;
time *= 60;
min = (int) time;
time -= min;
time *= 60;
sec = (int) time;
printf("3.76시간은 %d시간 %d분 %d초입니다.", hour, min, sec);

도전문제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main(void)
{
double weight;
double height;
double bmi;
char res[20];

printf("몸무게(kg)와 키(cm) 입력 : ");
scanf("%lf%lf", &weight, &height);

height /= 100;

bmi = weight / (height * height);
printf((bmi >= 20 && bmi < 25) ? "표준입니다\n" : "체중관리가 필요합니다\n");

return 0;
}




오늘은 C언어의 변수와 연산자에 관해 정리해 보았습니다.

읽어주셔서 감사합니다. 👋