연산자의 우선 순위와 결합성
C 언어의 기본 자료형
실수 자료형의 정밀도
- 보편적으로 정수는 int형으로 표현하는데, 실수는 보편적으로 double형을 쓴다.
- float형 보다는 정밀도가 높으면서 long double형 보다는 부담이 덜 되기 때문이다.
- double형으로 데이터를 받는 경우 서식 문자는 %lf를 사용한다.
정수형 자료형의 특성
- 기본 자료형 앞에 unsigned를 붙이는 경우 MSB까지도 데이터의 크기를 표현하는데 사용하게 되므로 데이터의 표현 범위가 양의 값으로 두 배가 된다.
- 기본 자료형 중에서도 정수형 자료형(char, short, int...)에만 붙일 수 있다.
- 실수형 자료형에는 붙일 수 없음에 유의하자!
리터럴 (literal) 상수
이름이 없는 상수를 가리켜 '리터럴 상수'라 한다.
리터럴 상수도 기본적으로 자료형이 결정된다.
- 아래 코드에서 등장하는 'A', 3, 3.15는 모두 상수이다.
- C 언어는 기본적으로 상수건 변수건 간에 자료형을 결정짓는다. 그래야 적절히 메모리 공간을 할당하고 값을 저장할 수 있다.
- 'A'는 char형으로 인식, 5는 int형, 3.15는 double형으로. 이것이 기본적으로 C 언어가 상수를 인식하는 방법이다.
- 오해하지 말자. 대입 연산자의 오른쪽에 선언하고 있는 상수에 맞게 변수를 선언한 것뿐이다.
접미사에 따른 다양한 상수의 표현
float f = 3.14f;
3.14는 double형인데, 위 표시법은 folat형 상수로 인식하라는 의미가 된다.
심볼릭(Symbolic) 상수
심볼릭 상수 : 이름을 지니는 상수
선언하는 방법
- const 키워드를 이용하는 방식
변수 선언 시 const 키워드를 붙여주면 된다.(단, 상수는 선언과 동시에 초기화해야 한다.)
상수의 이름은 일반적으로 대문자로 표시하는 것이 좋다. - 매크로를 이용하는 방식
특수 문자(escape sequence)
서식 문자의 종류와 그 의미
부동소수점 표현 방식
흔히 공학용 수치 계산에서 사용되는 방법으로 표현하고자 하는 실수를 효율적으로 표현할 수 있다.
다음은 실수 표현이 어떤 값을 의미하는지 보여주고 있다.
- %e에 의한 부동소수점 표현 방식이 실수를 효율적으로 표현하기는 하지만
- %f에 의한 출력이 보다 익숙하게 느껴질 것이다.
- 따라서 표현하고자 하는 실수의 값이 소수점 이하 6자리 안에서 표현 가능하다면 %f를 이용해 출력
- 이를 넘길 경우에만 %e를 사용해서 출력하기를 원할 수도 있다.
- 이러한 경우에 사용하는 것이 %g, %G이다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #include <stdio.h> int main(void) { double d1 = 1.23e-3; // 0.00123 double d2 = 1.23e-4; // 0.000123 double d3 = 1.23e-5; // 0.0000123 double d4 = 1.23e-6; // 0.00000123 printf("%g \n", d1); // 0.00123 printf("%G \n", d2); // 0.000123 printf("%g \n", d3); // 1.23e-005 printf("%G \n", d4); // 1.23E-006 return 0; } | cs |
필드 폭 지정의 예
조건에 따른 흐름의 분기
- if와 else
- 조건 연산자 / 삼항 연산자
조건 ? A : B
조건이 true인 경우 A를 반환 : 조건이 false인 경우 B를 반환 - continue & break
continue - 돌던 루프의 남아 있는 부분을 그냥 건너뛰기 (생략)
break - 반복문 탈출 - switch
- goto
goto문은 불필요 - 프로그램의 흐름을 복잡하게 하기 때문
C 언어와 같은 절차지향적 언어에서 문법적 요소가 프로그램의 흐름을 복잡하게 한다는 것은 큰 단점. 따라서 사용은 가급적 자제.
함수 정의 / 선언
- C 언어의 핵심은 함수다. 함수는 잘 정의하는 것도 중요하고, 잘 정의된 함수를 가져다 쓰는 것도 중요하다. 함수를 잘 구성하는 프로그래머는 실력 있는 프로그래머이다.
- 함수는 호출되기 전에 미리 정의되어야 한다.
- 함수 정의 - 함수의 이름을 정하고 기능을 구현하고 전달 인자와 반환 값의 형태를 결정짓는 것
전달 인자와 반환 값 형태를 가지로 함수를 나눈다면 총 4가지 - 전달 인자: 유 / 반환 값: 무
- 전달 인자: 유 / 반환 값: 무
- 전달 인자: 무 / 반환 값: 유
- 전달 인자: 무 / 반환 값: 무
변수의 범위
변수가 선언되는 위치가 함수와 깊은 관계가 있다.
변수는 선언되는 위치에 따라 크기 전역 변수와 지역 변수로 나뉜다.
차이점 - 메모리상에 존재하는 기간, 변수에 접근할 수 있는 영역
- 지역 변수
{} 중괄호 내에 선언된 변수
함수가 호출될 때 메모리상에 올라갔다가 함수가 종료되면 메모리상에서 사라진다.
모든 매개 변수는 지역 변수다.
매개 변수 - 함수가 실행되는 동안에만 유효하다는 특징을 가진다. - 전역 변수
프로그램 어디에서나 접근이 가능한 변수
프로그램이 시작하자 마자 메모리상에 올라가서 프로그램이 종료될 때까지 존재
초기화해 주지 않을 경우, 자동으로 0으로 초기화된다. (지역변수와 차이점)
지역 내에서는 지역 변수가 전역 변수보다 우선시된다.
즉, 지역 내에서 선언된 지역 변수는 외부에 선언된 같은 이름의 전역 변수를 가린다. - static 변수
변수 선언 시 static 키워드를 붙여서 선언한 변수
함수 내에 선언된 static 변수는 특성이 전역 변수와 비슷하다.
전역 변수는 메모리 공간을 할당받고 초기화가 이뤄지면 프로그램이 종료될 때까지 소멸되지 않고 초기화도 두 번 다시 일어나지 않는다. - register 변수
변수는 CPU의 '레지스터' 메모리 영역에 저장된다.
명령이 아니라 요청에 가깝다. 무시될 수도 있기 때문이다.
CPU의 레지스터는 크기가 제한되어 있는 메모리 공간이기 때문에 할당이 여의치 않을 경우 충분히 무시될 수 있다.
컴파일러가 코드 최적화를 수행하기 때문에 register 키워드를 붙여서 성능이 향상될 부분에는 우리가 붙여주지 않아도 컴파일러가 알아서 붙여준다. (개념만 이해하기)
전역 변수 vs static 변수
전역 변수의 변경은 전체 프로그램의 변경으로 이어지기 쉽움. 이러한 단점을 static변수가 해결.
static 변수는 전역 변수의 특징을 일부 지니면서도 선언된 지역 내에서만 접근이 가능하기 때문.
가변 인자 함수
printf와 scanf는 가변 인자 함수로 구현되어 있다.
가변 인자 함수는 전달 인자의 개수가 다양한 함수를 말한다.
재귀적 함수 호출
재귀적 함수는 자료구조와 알고리즘에서 빠질 수 없는 개념이다.
함수 내에서 자기 자신을 다시 호출하는 형태의 함수 호출
재귀 함수를 정의하는데 있어서 탈출의 조건은 아주 중요하다.
재귀 함수 Design 사례
팩토리얼(factorial) 계산을 위한 함수를 구현
n! = n*(n-1)*(n-2)...*2*1
n! = n*(n-1)!
1 2 | f(n) = n*f(n-1) // n이 1 이상인 경우 = 1 // n이 0 인 경우 | cs |
Pseudo Code('수도 코드'라 발음) : 특정 프로그램 언어에 종족적이지 않은 가짜 코드
1 2 3 4 5 | // 시작 조건 : n은 0 이상이다. 시작(START): f(n) 호출 1. 만약에 n이 0dlaus 1을 반환 2. 그렇지 않다면 n ? f(n-1)을 반환 끝(END) | cs |
Pseudo Code를 C 언어로 구현
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include <stdio.h> int f(int n); int main(void) { int val; int result; printf("정수 입력: "); scanf("%d", &val); if (val<0) { printf("0 이상을 입력해야 합니다.\n"); return 1; } result = f(val); // factorial 계산 printf("%d!의 계산 결과 : %d\n", val, result); return 0; } int f(int n) { if (n == 0) // 만약에 n이 0이면 1을 반환 return 1; else return n*f(n - 1); // 그렇지 않다면 n ? f(n-1)을 반환 } | cs |
|
'Books > 열혈강의 C 프로그래밍' 카테고리의 다른 글
[열혈C] 06. Part3 Chapter20 도전! 프로그래밍 THREE (0) | 2018.04.27 |
---|---|
[열혈C] 05. Part3 Chapter19 함수 포인터와 void 포인터 (0) | 2018.04.26 |
[열혈C] 04. Part3 Chapter18 다차원 배열과 포인터의 관계 (0) | 2018.04.25 |
[열혈C] 03. Part3 Chapter16-17 내용 정리 (다차원 배열 / 포인터의 포인터) (0) | 2018.04.24 |
[열혈C] 02. Part2 내용 정리 (포인터와 배열의 시작) (0) | 2018.04.19 |