[C언어] 02. 기본 변수와 입력
프로그램은 결국 데이터를 다루는 일이고, 그 데이터를 담는 그릇이 변수다. 오늘은 변수가 무엇이고 어떻게 선언·저장·출력하는지, 그리고 사용자에게서 값을 입력받는 scanf까지 정리했다.
1. 변수와 자료형
프로그램이 사용하는 데이터를 일시적으로 저장하기 위한 메모리 공간이다. 변수에는 값, 이름, 자료형(크기), 주소가 따라붙는다.
C에서 변수는 쓰기 전에 반드시 자료형과 함께 선언해야 한다. 선언은 "이런 타입의 변수를 쓰겠다"고 컴파일러에 미리 알리는 일이고, 컴파일러는 이를 보고 알맞은 크기의 메모리를 확보한다.
대표적인 자료형은 정수형 int, 실수형 double, 문자형 char 등이다. (참고로 C에는 원래 논리형 bool이 따로 없어, 정수 0/1로 참거짓을 표현했다.)
변수 이름(식별자) 규칙
- 영문자·숫자·밑줄(
_)로만 구성한다. - 첫 글자는 영문자 또는 밑줄이어야 한다(숫자로 시작 불가).
- 중간에 공백을 넣을 수 없다.
- 대문자와 소문자는 구별된다(
num과Num은 다른 변수). - C 키워드(
int,return등)는 이름으로 쓸 수 없다.
규칙을 지키는 선에서, 변수의 역할을 잘 드러내는 이름을 고르는 게 좋은 습관이라고 한다.
2. 값 저장과 출력
변수에 값을 넣는 것은 대입 연산이다. = 기호를 쓰는데, 수학의 "같다"가 아니라 "오른쪽 값을 왼쪽에 저장하라"는 뜻이다. 이걸 수학의 등호로 받아들이면 처음에 꼭 헷갈린다.
int x = 20; // 선언과 동시에 20을 저장
x = 30; // 값은 언제든 바꿀 수 있다
=는 값을 저장하는 대입 연산이고, ==는 두 값이 같은지 비교하는 관계 연산이다. 초심자가 조건문에서 ==를 쓸 자리에 =를 잘못 쓰는 실수가 잦으니 처음부터 구분해두자.
출력은 printf에 형식 지정자를 써서 변수 값을 끼워 넣는다.
int x = 20, y = 10;
printf("두 수의 합: %d\n", x + y); // %d 자리에 정수 30
printf("원주율: %lf\n", 3.14); // 실수(double)는 %lf
형식 지정자의 개수와 자료형은 뒤따르는 값과 정확히 일치해야 한다. %d 자리에 실수를 주거나 개수가 안 맞으면 엉뚱한 값이 출력된다. 실제로 %d에 실수를 넣어보니 의미 없는 숫자가 찍혀서, 형식 지정자와 값의 타입을 맞추는 게 중요하다는 걸 알았다.
#include <stdio.h>
int main(void) {
int a = 20, b = 10;
printf("합: %d\n", a + b);
printf("차: %d\n", a - b);
printf("곱: %d\n", a * b);
printf("몫: %d\n", a / b);
return 0;
}
3. 사용자 입력: scanf
scanf는 키보드 입력을 받아 변수에 저장한다. 형식 지정자, 그리고 변수의 주소(&)가 필요하다.
int n;
scanf("%d", &n); // 변수 이름 앞에 & 를 붙인다
형식 지정자는 printf와 거의 같지만, 결정적 차이가 변수 앞의 &다.
scanf는 입력받은 값을 "어디에 저장할지"를 알아야 한다. & 는 그 변수가 위치한 메모리 주소를 가리키는데, scanf에 이 주소를 넘겨야 그 자리에 값을 써넣을 수 있다. printf는 값만 읽어 출력하므로 &가 필요 없다. 이 주소 개념이 나중에 포인터의 토대가 된다.
처음엔 &를 왜 붙이는지 몰라 그냥 외웠는데, "값을 받아 저장하려면 저장할 위치(주소)를 알려줘야 한다"로 이해하니 출력엔 왜 안 붙는지까지 한 번에 정리됐다.
#define _CRT_SECURE_NO_WARNINGS // 비주얼 스튜디오에서 scanf 오류 방지
#include <stdio.h>
int main(void) {
int a, b;
scanf("%d %d", &a, &b);
printf("합: %d\n", a + b);
return 0;
}
4. 수업 코드로 보는 합계와 평균
두 정수를 입력받아 합계와 평균을 구하는 문제는 변수·입력·출력의 기본형이다.
int iFirst;
int iSecond;
int iSum;
double dAverage;
printf("정수 2개 입력: ");
scanf("%d %d", &iFirst, &iSecond);
iSum = iFirst + iSecond;
dAverage = iSum / 2.0;
printf("합계: %d\n", iSum);
printf("평균: %.2f\n", dAverage);
| 입력 | iSum | dAverage |
|---|---|---|
| 70, 80 | 150 | 75.00 |
| 10, 11 | 21 | 10.50 |
평균에서 2가 아니라 2.0을 쓰는 이유는 실수 나눗셈을 만들기 위해서다. 정수끼리 나누면 소수점이 잘린다.
오늘 느낀 점
=가 "같다"가 아니라 "저장하라"라고 인식하면, 이후x = x + 1같은 표현이 자연스러워진다.- 형식 지정자와 값의 타입을 안 맞춰 엉뚱한 출력이 나온 경험이, "C는 타입에 엄격하다"는 감각을 일찍 심어줬다.
scanf의&를 주소 개념으로 이해하니, 나중에 나올 포인터의 출발점이 여기였다는 게 보였다. 지금 잘 잡아두면 뒤가 수월하겠다.
한 걸음 더
- 자료형마다 메모리 크기가 정해져 있어, 담을 수 있는 값의 범위도 한정된다. 예를 들어 보통 4바이트인
int는 약 ±21억까지만 표현한다. 이 범위를 넘으면 값이 엉뚱하게 뒤집히는 오버플로가 생기므로, 큰 수를 다룰 땐long long같은 더 큰 자료형을 쓴다. int a / b처럼 정수끼리 나누면 결과도 정수가 되어 소수점 이하가 버려진다(7 / 2는 3). 실수 결과가 필요하면 한쪽을 실수로 만들어야 한다(7.0 / 2는 3.5). 자료형이 연산 결과를 좌우한다는 점은 C에서 특히 자주 부딪히는 함정이다.scanf의&를 빠뜨리면 컴파일은 되더라도 실행 중에 프로그램이 비정상 종료되기 쉽다. 값을 엉뚱한 메모리 위치에 쓰려다 사고가 나기 때문이다. "입력엔 &, 출력엔 없음"을 처음부터 손에 익혀두면 이런 사고를 예방할 수 있다.