C언어 표준 함수
데니스 리치가 만들어서 배포 했다. 오픈 소스로 되어 있어서 visual c++에서 실제로 소스를 볼 수 있다.
*.obj를 쓰는 이유
"컴파일을 피해 속도를 향상시킬수 있고 소스관리를 원활하게 할 수 있다. 라는 의미도 있지만 *.obj는 소스가들어 있지 않아서 자신이 만든 소스를 다른사람에게 보여주기 싫은 경우에 *.obj파일을 사용하거나 *.obj 있는 내용을 볼 수 없으므로 자신의 생가그이 범위를 줄이기 위해 사용된다. 또한 헤더파일 선언이 잘못 되었거나 시간이 과거와 현재로 움직일때 소스 전체를 다시 컴파일 해야 하기 때문에 *.obj파일을 사용하면 컴파일 속도를 향상시킬수 있다. *.obj파일은 기계어로 되어있어서 *.obj파일만 보고 소스를 유추하는것은 힘들다.
라이브러리파일이 등장한 이유
일반적으로 소스를 여러개를 나누어 *.c -> *.obj -> *.exe 파일 순으로 실행한다.
소스코드를 *.c라고하면 컴파일 후 *.c -> *.obj 파일로 바뀌고 *.obj 파일들이 모여 링커에 의해 링크 되어 *.exe 파일이 실행된다.여기서 소스가 바뀌면 소스가 바뀐 소스코드 부분만 컴파일 되어 새로운 *.obj 파일이 만들어지고 변경되지 않은 기존의 *.obj 파일들이 모여 링크되어 *.exe파일이 생성된다. 따라서 *.c코드가 절대 바뀌지 않는 소스라면 *.c대신 *.obj 파일을 넣어 실행하기도 한다. 이와 같이 소스파일 대신 *.obj 파일을 사용해서 컴파일 수를 줄여 실행 속도를 향상시킬 수 있다. 하지만 obj의 큰 단점이 있다. *.exe파일에서 *.obj의 여러개의 함수 중 단 한개의 함수만 필요하더라도 *.obj의 모든 함수가 *.exe 파일에서 실행되어 실행파일이 무거워지는 단점이 있다. 따라서 obj에 함수가 많으면 많을수록 손해이다. 따라서 대부분 *.obj파일을 *.lib으로 바꾸어서 실행된다. *.lib파일은 사용되는 함수만 실행파일에서 사용되기 때문이다.
헤더파일
*.lib 파일에 있는 함수를 사용하기 위해서 각 함수의 원형을 반드시 선언해야 한다.
하지만 매번 이런 과정을 계속 반복하면 힘이들고 시간낭비가 되어 헤더파일 .h를 사용하여 함수의 원형 대신 헤더파일을 사용한다. 헤더파일에 미리 함수의 원형이 선언되어 있다.
전처리기
프로그래머가 원하는 사항을 컴파일러에게 직접 지시하는 문법으로 #기호를 사용하며 끝에 ;(세미콜론)을 사용하지 않는다.
#include 전처리기
#include 전처리기는 컴파일러에게 자신이 명시한 파일을 읽도록 지시하는 전처리기 이다.
#include <읽을파일 이름> --- 컴파일러가 기본적으로 제공하는 헤더파일
#include "읽을파일 이름" --- 프로그래머가 정의해 사용하는 헤더파일
" "이 < >을 포함하는 개념이다. 즉 < >를 " "으로 써도 상관이 없지만 컴파일러가 힘들고 다른 프로그래머들이 오해할 수 있기 때문에 형식에 맞추어 사용하는것이 좋다.
상수와 변수의 연산
X + 2 + 3 과 2 + 3 + X를 연산 과정을 비교해 보면 아래와 같다.
X + 2 + 3은 우선 컴파일러가 X+2를 하고 (X+2)+3을 하는 double add가 된다.
2 + 3 + X는 컴파일러가 2+3을 5로 인식해 5+X로 인식하는 add가 된다.
즉, 연산에 있어서 상수가 앞쪽에 있는 것이 좋다. 상수 치환을 잘 사용하면 코드 전체에 좋은 효과를 줄 수 있다.
요즘은 컴파일러가 좋아서 double add가 잘 발생하지 않지만 상수 치환을 잘 사용하도록 해보자
#define Max 2+3 --- 컴파일러가 2+3을 5로 바꾸고 처리한다.
#define 전처리기
#define 전처리기는 상수나 명령문을 치환하는 전처리기이다.
#define으로 상수를 치환할때 다음과 같이 사용한다.
#define MAX_COUNT 3 --> 3이라는 상수를 MAX_COUNT로 치환하라는 의미이다.
#define을 사용하는 두가지 이유가 있다. 첫째는 소스코드에 변화가 왔을 때 유지 보수를 편하게 하기 위해서 사용한다.
둘째는 상수에 의미를 부여하기 위해서이다. 즉, 소스코드를 남이 보았을때 상수에 대한 의미를 알 수 있기 때문이다.
#define으로 명령어를 치환할때 다음과 같이 사용한다. 이를 매크로 함수라고 부른다.
#define SQUARE_VALUE(a) (a*a)--> SQAURE_VALUE(a)를 (a*a)로 바꾸라는 뜻이다.
C 표준 라이브러리
운영체제 별로 화면에 문자를 출력하는 과정과 방법이 다르다. 따라서 C언어가 문자 출력 기능을 문법으로 제공하면 운영체제별로 문자를 출력해야할 C문법이 달라지는 문제가 발생한다. 이러한 단점을 극복하기 위해 C언어는 시스템에 영향을 받는 요소들을 고정된 문법으로 제시하지 않고 함수라는 개념을 재공한다. 하지만 프로그래머가 직접 문자를 출력하는 함수를 만든는 것은 매우 어려운 일이기 때문에 C언어 표준함수에 운영체제 별로 다양한 기능을 구현하는 함수가 제공되어있고 C언어 표준 함수들이 C표준 라이브러리에 속해 있다.
표준 출력 함수
콘솔출력 --- 모니터로 내보내는 출력 (특수한 출력)
다양한 기능이 있다. ex) 콘솔 출력되는 문자에 색을 넣을 수 있다.
표준출력 --- 스피커, 프린트, 파일 등 해당 시스템이 가장 기본적으로 사용하는 출력이다.
다양한 기능이 없다. 노란색 소리(X)
표준출력함수에는 putchar, putc 가 있다. 단일 출력 함수라고 한다.
putchar(70); 아키스코드값 70에 해당하는 문자 F가 출력된다.
putc('F'); 문자 F가 출력된다.
puts는 문자열 출력함수이다.
puts("Hello World"); Hello World가 출력된 후에 줄바꿈이 일어난다.
문자열 출력함수 printf(print + format)
printf 함수는 표준 출력 함수 중에서 가장 많이 사용하는 함수로서 프로그래머가 일정한 형태를 만들어서 문자열을 출력할 수 있다.
printf 함수의 특징으로 %서식 지정 키워드를 사용하여 변수 값을 일정한 형식으로 출력할 수 있는 것이다.
d=decimal(10진수 정수), f=float(실수), c=character(문자), s=stirng(문자열), o=octal(8진수), x=hexa(16진수)의 줄임말이다.
printf 사용법
int value1 = 5;
int value2 = 3;
printf("%d %d", value1, value2);
출력 결과 : 5 3
value1, value2 변수에 저장된 정수를 출력한다.
int temp = 6; int data = 5 * temp;
printf("5 * %d = %d", temp, data);
printf("5 * %d = %d", temp, 5 * temp);
출력 결과 : 5 * 6 = 30
출력결과를 보면 data와 5*temp의 출력 값이 같다.
% 키워드 중심의 출력 특성 확인하기
char value = 70;
printf("%c의 ASCII 값은 %d입니다.", value, value);
출력 결과 : F의 ASCII 값은 70입니다.
실수와 정수를 표현하는 방식이 다르다.
float data = 3.1f;
printf("%f", data);
출력 결과 : 3.1000000
float data = 3.1f;
printf("%f %d", data, data);
출력 결과 : 3.1000000 -107374182
-107374182를 보고 쓰레기 값이라고 할 수 있지만 쓰레기 값이 아닌 의미가(?) 있는 값이라고 할 수 있다.
-107374182을 16진수로 출력해보면 0xC0000000이 나오고 data의 변수값을 바꾸어도 일정하게 -107374182라는 수가 나옴을 알 수 있다.
이것을 보고 -107374182이 출력이 된다면 잘못된 형식으로 인해 오류가 나온다는 것을 일정한 에러값으로 알려주고 있는 것이다.
%d와 %u는 변수 크기를 4바이트 값으로 변환하여 출력
char data = -1;
printf("%d, %u", data, data);
예상출력결과와 실제출력결과가 다른 이유은 %d 와 %u가 4바이트(32비트) 크기의 정수 기반으로 값을 출력하기 때문이다.
char value = -1; int data = value;
위와 같은 소스는 경고가 나오지 않는다. 즉, 작은 바트이를 큰바이트에 대입하는것은 경고가 나오지 않는다.
value가 data에 들어가기 위해서는 vlaue가 4바이트로 늘어나야한다. 바이트가 늘어날때 부호비트(최상위비트)가 1이면 다 1로 들어가고 부호비트(최상위비트)가 0이면 모두 0으로 들어간다. 부호비트(최상위비트)로 늘어나야 부호가 바뀌지 않고 값이 유지 되기 때문이다.
%o는 8진수, %x는 16진수 형태로 출력
int data1 : 10; 10진수 ---> 10
int data2 : 010; 8진수 --->8
int data3 : 0x10; 16진수 ---> 16
printf("%x, %d, %o", data1, data2, data3);
출력결과 : a, 8 ,20
%e는 실수를 지수 형태로 출력
float data = 31.14;
printf("%f, %e, %E", data, data, data);
출력결과 : 31.140000, 3.1140003e-1, 3.1140003E-1
출력 칸수 조절하기
int data = 7;
printf("[%d] [%5d}", data, data);
출력결과 : [7] [ 7] (공백이 4개들어감)
오른쪽 정렬과 왼쪽 정렬
int data = 7;
printf("[%5d] [%05d] [%-5d]", data, data, data);
출력결과 : [ 7] [00007] [7 ]
[ 7](오른쪽 정렬) [00007](공백대신 0을 채움) [7 ](왼쪽 정렬)
출력 문자열 정렬 이유
디지털로 주어진 숫자는 값의 범위를 직관적으로 보기 힘들다. 따라서 직관적으로 정도의 범위를 눈에 띄게 볼 수 있도록 하기 위해서 문자열을 정렬해서 사용한다.
실수의 소수점 자릿수 지정하기
.마침표를 사용하여 출력할 소수점 이하 자릿수를 지정할 수 있다. 아래와 같이 사용하면 된다.
double data = 3.141592;
printf("[%f] [%.2f] [%7.3f] [%-7.3f]", data, data, data, data);
출력결과 : [3.141592] [3.14] [ 3.141] [3.141 ]
단, C언어는 반올림을 사용하지 않지만 printf는 반올림을 사용하기 때문에 돈과 같은 것에서는 중요하게 사용해야 한다.
제어코드 사용하기
아스키 표에는 소리를 내거나 콘솔의 출력과 입력의 현재 위치를 알려주는 캐럿(Caret, 문자로 깜빡임) 위치를 변경할 수 있는 제어코드가 있다.
제어코드는 키보드에 있는 문자가 아니기 때문에 제어코드를 직접 입력할 수 없기 때문에 C언어는 \(역슬래시)와 키워드로 제어코드를 사용할 수 있는 문법을 제공한다.
\t visual studio에서 tab키는 4칸, 기본적인 출력장치에서는 8칸이다.
위의 표를 보면 표준출력에서 다음줄 맨처음 칸으로 이동하려면 \r\n을 써야하지만 printf에서만 \n을 사용해도 된다.
대입 연산자
C언어에서는 =(등호) 기호로 표현한다. C문법에서 =(등호) 는 '같다'는 뜻이 아니다.
변수에 상수 값 또는 다른 변수에 값을 대입할 때 사용한다.
산술 연산자
상수 또는 변수 값을 이용한 산술 연산에 사용되는 연산자
+ 연산자 : 더하기 연산자
- 연산자 : 빼기 연산자
* 연산자 : 곱하기 연산자
/ 연산자 : 나눗셈의 몫을 구하는 연산자
%연산자 : 나눗셈의 나머지를 구하는 연산자
증감 연산자
++ 증가 연산자 : 변수가 가지고 있는 값을 1 증가
-- 감소 연산자 : 변수가 가지고 있는 값을 1 감소
덧셈 연산자(이항연산자)는 두 개의 메모리가 연산에 사용되고 증가 연산자(단항연산자)는 한 개의 메모리가 연산에 사용된다.
따라서 특별한 경우가 아니라면 증가 연산자(단항연산자)를 사용하는 것이 속도가 빠르고 효율적이다.
증감 연산자의 전위형과 후위형
후위형 : 연산하고 난 뒤 값을 증감한다
전위형 : 값을 먼저 증감한 뒤 연산한다.
관계 연산자
두 수치 값을 비교하여 그 결과 값을 진릿값(참, 거짓)으로 얻는 연산자이다.
연산의 결과가 참이면 1, 거짓이면 0을 반환한다.
진리값을 판달할 때 0을 제외한 모든 값은 참이다. 판단 기준은 0만 거짓이다.
int a = 2<3; 2<3이 참이기 때문에 a에 1이 대입된다.
=, == , != 연산자
= 연산자 : 대입연산자
== 연산자 : '같다'라는 관계를 나타내는 연산자
!= 연산자 : '같지 않다'라는 관계를 나타내는 연산자.
논리 연산자
A와 B의 상황을 일정한 규칙으로 연결해주는 연산자
실제 프로그램을 할때 많이 사용된다.
논리연산자에는 특징이 있다.
A&&B(논리곱) : 내가 특정대상을 0으로 만들수 있다.
A가 Flase이면 B의 진릿값에 상관없이 결과 값은 False 이다.
A||B (논리합) : 내가 특정대상을 1로 만들수 있다.
A가 True이면 B의 진릿값에 상관없이 결과 값은 True 이다.
위와 같이 조건문이 아닌데 조건문처럼 사용할 수 있다는 특징을 가지고 있다.
연산 방향
연산자 우선순위가 같은 연산자들에 대해서도 연산의 우선 순위를 정한다.
컴퓨터에서는 '연산 방향'을 반드시 사용해야 한다. 아래의 예를 보자
2 * 3 / 4를 왼쪽에서 오른쪽으로 연산해 보면
(2*3)/4 = 6/4 = 1
오른쪽에서 왼쪽으로 연산해 보면
2*(3/4) = 2*0 = 0
즉 연산 방향에 따라 결과 값이 다르게 나올 수 있다는 것을 알 수 있다.
제어문
프로그램의 실행 흐름을 제어하는 문법이다.
C언어에서는 특정 작업을 반복하거나 예외를 처리할 수 있도록 두 가지 제어문(조건문, 반복문)을 제공
조건문
특정 조건을 부여하여 해당 조건을 만족하면 지정한 문장을 수행하는 문법이다.
조건은 수식으로 표현하며 수식의 진릿값이 True(1)이면 문장을 수행
if 조건문
문법이 간단하고 ( )괄호 안에 있는 조건 수식의 결과 값이 참이면 뒤따르는 명령문 한개를 수행한다.
단일 문장을 수행하는 if 조건문
명령문1;
if(조건수식) 명령문2;
명령문3;
오직 명령문2;가 if(조건수식)에 영향을 받는 구조이다.
복합 문장을 수행하는 if 조건문
명령문1;
if(조건수식) {
명령문2;
명령문3;
}
명령문4;
if(조건수식)에 영향을 받는 명령문은 복합 명령문인 { 명령문2; 명령문3; } 이다.
구문 오류 (Syntax Error)
프로그래밍 언어가 제공하는 규칙을 제대로 지키지 않았을 때 발생한다.
컴피일하기 전에 오류가 난 부분이 빨간줄 표시가 되어 있고 컴파일 할때 컴파일러가 체크해서 알려준다.
의미상 오류 (Semantic Error == bug)
문법적으로 맞지만 의미적으로 틀릴 때 발생한다.
오류가 많이 난다면 오류를 줄이는 프로그래밍 습관을 가지도록 습관을 고쳐야 한다.
if ~ else ~ 조건문
서로 반대되는 조건을 한 번에 표현하는 형식
조건문을 피해갈 수 있으면 피해가는 것이 좋다.
요즘은 컴퓨터가 좋아져서 한번에 명령문 여러개를 읽어와서 false가 나오면 들어오는 명령어를 다 버리지는 않지만 많이 사용하면 많이 사용할수록 효율성이 떨어지니 조건문을 최대한 줄이는것이 좋다.
if~else와 조건 수식 연산자 중 더 편하다고 생각되는 조건문을 사용하면 된다.
중첩된 if ~ else ~ 문은 { }중괄호를 생략 가능하다.
if ~ else 중첩문에서 아무생각없이 순서를 나열하지 말고 가장 확률이 높은것을 위로 올려서 먼저 처리되게 하면 효율성이 향상된다.
단, 점수와 같은 흐름에서 80점이 확률이 높아서 if ~ else 문에서 제일 위로 올리면 90점 보다 작은지를 처리해야하는 소스를 추가해야 하기 때문에 많은 경우들을 생각해서 흐름에서 벗어나지 않는 상황에 한에서 가장 확률이 높은것을 맨 위로 올리는 것이 좋다.
조건 수식 연산자 == 삼항 연산자
결과 값 = (조건 수식) ? 수식1 : 수식2;
if~else~ 조건문과 비슷한 형태를 가지는 연산 수식이다.
단일 문장으로 구성된 명령문만 사용이 가능하고 { }중괄호를 사용하는 복합 문장은 사용이 불가능 하다.
조건 수식이 참이면 수식1이 결과 값이 되고 조건 수식이 거짓이면 수식2가 결과 값이 된다.
'Programming > TIPS 17기' 카테고리의 다른 글
Day-6 배열과 문자열, 포인터 (2) | 2017.07.16 |
---|---|
Day-5 지역변수와 전역변수, 배열과 문자열 (2) | 2017.07.14 |
Day-4 조건문, 반복문,시프트 연산자와 비트연산자 (1) | 2017.07.07 |
Day-2 자료형, 상수와 변수, 함수 (0) | 2017.07.03 |
Day-1 프로그램과 C언어, 자료형 (1) | 2017.06.28 |