2강
이미 개강한지 5주가 지났습니다. 이미 C언어 수업을 꽤 진행 하셨을 겁니다. 거기에 더해 신입생 테스트 결과 여러분의 수준이 낮지 않음을 느꼈고. 진도를 많이 빼도록 하겠습니다. 오늘 수업의 문법을 이미 경험 헀다고 가정하고 빠르게 훑어보고, 수업 때 안다뤘을 만한 테크닉 등을 더해 살펴볼 예정입니다.
목차
C언어 기초
변수
자료형
상수
연산자
입출력
반복문
조건문
C언어 기초
컴파일러, 링커
프로그래밍 언어는 컴퓨터에게 명령하기 위해 있는 언어라고 말씀드렸습니다. 사실 컴퓨터는 이 언어를 알아들을 수 없습니다. 컴퓨터는 완전히 0과 1로만 이루어져 있고 0 과 1에 의해 동작합니다. 따라서 우리가 작성한 C언어 코드를 0과 1 즉 기게어로 변환 해 주는 것이 컴파일러 입니다.
컴파일러가 .c 파일을 .obj파일로 바꿔줍니다. 이 파일은 0과 1로만 이루어져 있는 컴퓨터가 바로 실행할 수 있는 파일이 됩니다.
우리가 이 파일을 실행하기 위해선 .exe 파일로 변환해줘야 합니다. .obj 파일을 .exe 파일로 바꿔주는 것이 링커입니다.
비주얼 스튜디오는 이 컴파일러와 링커 역할을 동시해 해주는 프로그램 입니다.
전저리
전처리라는 것은 컴파일러가 컴파일을 하기 전에 처리하는 내용을 말합니다.
#으로 시작하며 몇가지만 소개해드리겠습니다.
include
include 는 헤더파일을 가져오는 전처리 구문입니다. 헤더파일에는 유용한 함수와 상수들이 있습니다. 우리는 #includ 라는 구문을 통해 printf() 등을 사용할 수 있는 것입니다.
define
#define a b 를 하면 컴파일을 하기전에 a를 b로 완전히 치환해 버립니다. 주로 상수를 만들거나 매크로 함수를 만들 때 사용합니다.
주석
주석은 프로그램에 영향을 주지 않는 글을 말합니다. 한줄 주석 : // (주석내용) 여러줄 주석 : / 주석 내용 1 주석 내용 2 / 코드의 핵심 원리나, 나중에 보면 도움이 될만 한 내용을 주석으로 코드에 남겨두면 좋습니다.
기타
세미콜론은 모든 명령어 뒤에 써야 합니다.
중괄호는 포함 관계를 나타냅니다.
변수
변수는 정보를 저장할 때 쓰입니다. 변수를 만든다는 것은 컴퓨터 메모리 공간에 이름을 붙이는 것과 같습니다.
컴퓨터에서 모든 정보는 0과 1로 메모리에 저장됩니다. 보통 램이 메모리 역할을 합니다. 5라는 10진수도 사실 101이라는 이진수로 컴퓨터에 저장됩니다. 'A'라는 문자도 아스키 코드에 의해 65라는 숫자와 같고 메모리 상에 1000001라는 이진수로 저장됩니다.
만약 int a = 5 라는 변수를 만들었다고 하면 메모리 상에 어떤 공간에 101이라는 이진수로 5라는 십진수 값을 저장하고 그 공간 자체의 이름을 a라고 정해준 겁니다. 이제 a라는 공간에는 5라는 값이 저장되어 있죠.
당연히 a라는 공간에서 값을 가져오기 위해선 a가 메모리상의 어디에 위치해 있는지 알아야 하고 그것을 변수의 주소라고 합니다.
숫자 13은 1101의 이진수로 나타낼 수 있습니다. 한 자리는 한 비트로 나타낼 수 있으므로 숫자 13은 4비트의 크기를 가집니다. 따라서 숫자 13을 메모리에 저장하려면 4비트의 공간이 필요합니다.
C언어는 변수를 만들 때 이처럼 변수의 크기를 정해놓고 만들어야 합니다. 이런 형식을 자료형이라 하고 변수의 크기를 정해놓았기 때문에 최댓값과 최솟값을 가집니다. 자료형에서 자세히 설명하겠습니다.
변수 명명법
변수의 이름은 알파벳, 숫자, _ 로 이루어 집니다. 변수의 이름은 숫자로 시작할 수 없고 C언어에 존재하는 키워드와 같은 이름으로는 만들 수 없습니다. 이름 사이에 공백이 있을 수 없습니다. 변수의 이름은 가급적 의미있게 짓는 것이 좋습니다.
기타
변수를 사용하는 곳보다 밑에 변수를 선언하면 안됩니다.
변수에 값을 정해주지 않고 사용하면 안됩니다. 변수의 초기값을 지정해 주는 것을 변수의 초기화라고 합니다.
자료형
정수형 char int, long long int
정수는 보수방법을 이용해 표현합니다. int 형은 8바이트 = 32비트의 크기를 가지고 있습니다. 이 중 맨 앞의 비트는 부호를 나타내므로 실질적인 크기가 -2^31~2^31-1 이 되는 것입니다. long long int는 int의 두배이기 때문에 -2^63~2^63+1 의 값을 가집니다.
char
char는 저장하면 숫자로 저장되지만 문자로 취급됩니다. char은 character의 줄임말이고 1바이트의 크기를 갖습니다. 아스키 코드의 범위가 1바이트이기 때문입니다. 모든 문자는 실제로는 숫자로 계산됩니다. 여러분이 아스키 코드를 외울 필요는 없지만 문자가 사실은 숫자로 이루어져 있다는 사실은 알아야 합니다.
정수형의 오버플로우
변수에 자료형의 크기를 벗어나는 값을 저장하게 되면 오버 플로우 또는 언더 플로우가 일어납니다. char의 최댓값 127보다 큰 128을 입력하게 되면 -128로 바뀌게 됩니다. 129를 입력하면 -127로 됩니다. 즉 범위를 벗어난 만큼 최솟값에서 증가하게 됩니다. 언더플로우도 마찬가지로 범위를 벗어난 만큼 최댓값에서 감소하게 됩니다.
unsigned 키워드
문자형과 정수형에 unsigned를 붙이면 부호를 나타내는 비트까지 포함하여 절대값을 계산합니다. 따라서 음의 부호는 나타낼 수 없지만 그만큼 더 큰 양수를 저장할 수 있습니다. unsigned int 는 0~2^32-1의 값을 가집니다.
실수형 float, double
C언어에서 실수는 부호와 부동 소수점 방식을 사용합니다. float의 이름이 float인 이유입니다. 부호x가수x2^(127+지수) 로 나타냅니다. float는 소수점 6자리밖에 표현하지 못하기 때문에 오차가 많이 발생합니다. 그대신 double을 많이 사용합니다. double인 이유는 크기가 float의 두배이기 때문입니다.
형변환
자동 형변환
다른 자료형끼리 산술 연산을 할 때 자동으로 더 큰 자료형으로 형변환 시켜 줍니다.
강제 형변환
강제로 자료형을 변경해야 할 때 사용합니다.
int 끼리 나눗셈을 히면 소숫점 이하는 버려지게 됩니다. 따라서 둘 중 하나를 double로 변경해야 합니다.
5 / 3 = 1
(double)5 / 3 = 1.66666...
문자의 아스키 코드를 확인해 볼 수 있습니다. (게산할 때 굳이 형변환은 안해도 됩니다.)
(int)'A' = 65
상수
상수는 프로그램 실행 도중 변하지 않는 값을 말합니다.
리터럴 상수
리터럴 상수는 '말 그대로 상수'라는 소리입니다. int a = 5라 했을 때 5가 리터럴 상수입니다.
심볼릭 상수
만약 원주율을 3이라고 계산하고 소스 내부에 100번 이상 사용했다고 가정합시다. 그런데 더 정확한 원주율의 값이 필요해 3.141로 바꿔야한다고 합시다. 여러분은 소스 내부를 100번 뒤져서 3을 전부 3.141로 바꿔야 합니다. 게다가 원주율의 의미로 사용하지 않은 3까지 3.141로 바뀔 위험이 있기 때문에 신중하게 바꿔야 하게 될 것입니다.
심볼릭 상수는 리터럴 상수에 의미부여를 해 주는 것을 말합니다. 심볼릭 상수를 사용하는 이유는 1. 이름을 붙여서 리터럴 상수 자체에 어떤 의미가 있는지 알 수 있게 해주고 2. 상수의 값을 조정해야 할 때 한번에 관리하기가 편하기 때문입니다.
define 이용
#define 상수이름 값 으로 만들 수 있습니다.
const 이용
자료형 앞에 const 키워드를 붙여서 만들 수 있습니다. const가 유지보수할 때는 더 편한것 같습니다.
연산자
대입 연산자 =
대입 연산자는 변수에 값을 대입해주는 연산자입니다. a = b라고 했을 때 절대 a와 b가 같다고 이해하시면 안됩니다. 무조건 a에 값 b를 대입한다고 이해하셔야 합니다. 등호를 같다고 이해하면 많은 문제에 빠질 수 있습니다.
산술 연산자 + - / * %
%연산자는 굉장히 중요합니다. 모듈러 연산을 해주는 연산자입니다. 모듈러 연산이란 나머지를 구해주는 연산입니다. 5/3의 나머지가 2이므로 5%3 은 2 입니다. 모듈러 연산의 속성은 굉장히 중요합니다. (a + n*b)%n = a (b은 정수) 이 성질은 원판으로 이해할 수 있습니다. 모듈러 5 연산을 할 때 원판에 0 1 2 3 4의 숫자를 씁니다. 4%5를 하면 원판에서 4번 돌아 4의 값을 가집니다. 7%5를 하면 원판에서 7번 돌아돌아 2의 값을 가집니다. -1%5를 하면 원판이 뒤로 한칸 돌아 4의 값을 가집니다. 5%5를 하면 원판에서 5번 돌아 0의 값을 가집니다. 이렇듯 모듈러 연산은 무한한 범위의 수를 유한한 범위의 수로 좁힐 수 있다는 장점이 있습니다.
모든 산술 연산자는 =와 같이 쓸 수 있습니다. a += b -> a = a + b 이와같이 이해하시면 됩니다.
증감 연산자 ++ --
값을 1씩 늘리거나 1씩 줄이는 연산자 입니다. 앞에 붙이느냐 뒤에 붙이느냐에 따라 변수를 이용해 명령을 할 때 조금씩 다릅니다.
변수 뒤에 붙이게 되면 변수의 값이 명령을 실행한 뒤에 증가하게 됩니다.
변수 앞에 붙이게 되면 변수의 값이 명령을 실행하기 전에 증가하게 됩니다.
하지만 이를 이용해 복잡한 구조를 만드는것은 프로그램의 흐름을 알기 힘들게 만드므로 피합시다.
관계 연산자 > < >= <= == !=
값을 비교한 뒤 참이면 1을 반환하고 거짓이면 0을 반환하는 연산자 입니다.
논리 연산자 && || !
논리 연산을 한 뒤 참이면 1을 반환하고 거짓이면 0을 반환하는 연산자 입니다.
조건 연산자 (조건)?(참):(거짓)
조건이 참이면 참의 내용을 실행하고 거짓이면 거짓의 내용을 실행합니다.
비트 연산자 & | ~ ^ << >>
비트 연산자는 비트단위로 연산을 하는 연산자입니다. 가끔씩 쓰이므로 알아두면 좋습니다.
& : 두 비트 모두 1일 때 1입니다.
101 & 011 = 001
| : 한쪽 비트가 1이면 1입니다.
101 | 011 = 111
~ : 비트를 반전시킵니다.
~101 = 010
^ : 1이 홀수개면 1입니다.
101 ^ 011 = 110
101 ^ 010 ^ 110 = 001
<< : 비트를 왼쪽으로 옮깁니다.
101 << 2 = 10100
<< : 비트를 오른쪽으로 옮깁니다.
101 >> 2 = 1
& 연산자
변수의 주소를 가져옵니다.
, 연산자
한 줄에 명령어를 여러개 입력할 수 있습니다.
연산자 우선순위
연산자가 일렬로 늘어져 있을 때 먼저 연산하는 순서입니다.
입출력
printf()
데이터를 화면에 출력해주는 함수입니다. 문자열 포맷팅 방식을 사용합니다. 서식 문자를 사용하여 대입할 값을 뒤에서 하나씩 대응시켜 갑니다.
%d : 정수형
%f : 실수형
%c : 문자형
%s : 문자열
%% : %자체를 출력
\n을 통해 줄바꿈을 합니다. " 을 출력하려면 \ \" 처럼 \을 붙여줘야 됩니다.
서식문자 중간에 숫자를 넣어서 다양하게 활용할 수 있습니다.
공백 맞춰서 출력
printf("%5d\n", 12); printf("%5d", 123);
0을 맞춰서 출력
printf("%05d\n", 12); printf("%05d", 123);
반올림
printf("%.4f", 1.5555555); > 1.5556
getchar()
문자를 하나 입력받고 반환합니다. 버퍼를 비워줄 때도 많이 씁니다.
scanf()
입력받을 변수의 자료형과 주소를 받아서 입력을 받아줍니다. 출력과 달리 자료형을 정확하게 알려줘야 합니다. 문자열 입력에 관해선 문자열을 공부할 때 알아봅시다.
한 자리씩 입력받기
scanf("%1d",&n);
숫자의 합 (반복문 필요)
데이터 무시
scanf("%*2d%d",&n); > 처음 두자리의 숫자를 무시하고 나머지를 받음
1234로 입력하면 n = 34
scanf("%*d%d",&n); > 숫자하나를 무시하고 뒤에것을 받음
12 34로 입력하면 n = 34
콘솔로 값을 입력하면 줄바꿈인 \n도 같이 입력이 되는데 숫자를 입력받을 때는 이를 버퍼라는 임시 입력값 공간에 남겨둡니다. 따라서 숫자를 입력받고 문자를 입력받으려 하면 입력이 안됩니다. 그럴 땐 getchar()를 통해 버퍼에 있는 \n을 없애줘야 합니다.
또는 서식문자 사이에 공백을 넣어서 줄바꿈을 무시할 수 있습니다.
둘다 알아두세요
반복문
while(조건) {반복 내용}
조건이 참이면 내용을 실행합니다. 그리고 다시 조건을 보고 참이면 내용을 실행하고 다시 조건을.... 가장 단순한 반복 형태입니다.
for(선언부;조건;한바퀴 돌고 실행) {반복 내용}
특이하게 변수를 선언하는 부분이 있습니다. for문의 장점은 반복도 해주지만 인덱싱을 해준다는 점에서 가장 많이 쓰입니다. 쉽게 말해 반복문이 몇 번째 돌고 있는지 알 수 있다는 점이 장점입니다. for문은 구성 요소가 전부 빠져도 동작합니다. for(;;) {내용} 같이 사용하면 내용을 무한 반복하게 됩니다.
do~while()
반복을 할건데 무조건 한번은 실행해야 할 때 사용합니다. 입력의 범위를 검사할 때 사용하는 경우도 있습니다. 그 외에는 잘 쓰이진 않습니다.
하지만 이렇게쓰는게 더 좋습니다.
조건문
if(조건) {내용}
참이면 내용을 실행합니다.
if(조건) {내용1} else {내용2}
조건이 참이면 내용1 실행, 거짓이면 내용2를 실행합니다.
if(조건1) {내용1} else if(조건2) {내용2} else {내용3}
조건1이 참이면 내용1 실행, 거짓이면 조건 2 검사, 조건 2가 참이면 내용2 실행 거짓이면 내용 3 실행
Last updated
Was this helpful?