Category Archives: 정리하지 않음

글이 어느 정도 쌓이고 난 뒤에 정리하는 것이 타당해 보인다.

32비트의 메모리 제한

컴퓨터의 모든 것은 메모리 입출력과 연관이 있다. 32비트 운영체제에서는 할당할 수 있는 크기가 4G로 정해져 있다. 하지만 이를 전부 메모리에 할당할 수는 없다.

메모리 뿐 아니라 입출력 장치와 부가 장치를 위한 공간역시 할당되기 때문에 물리 주소 지도(PAM)는 메모리 할당에 전용할 수 없다. 하지만 물리 주소 확장(PAE)을 통해 32비트 운영체제는 예전부터 64G이상의 확장을 지원하고 있다.

06. 함수

함수의 구성

함수의 정의

프로그램은 함수들로 구성되고 함수들이 순서대로 실행됨으로써 프로그램이 제 기능을 발위한다. 즉, 함수는 프로그램을 구성하는 단위로서 프로그램의 부품 역할을 한다. C++에서는 함수의 이런 부품 역할을 객체가 대신 한다.

함수는 표준 함수와 사용자 정의 함수로 나뉜다. 표준 함수는 컴파일러와 함께 배포된 C언어와 함께 작성되어 제공되는 것이다. 사용자 정의 함수는 개발자가 필요에 따라 만들어 쓰는 함수이다.

함수

  • name : 함수의 이름. 이 이름을 통해 함수를 호출한다. 함수의 이름도 명칭이므로 명칭을 만드는 규칙대로 만든다.
  • 인수 목록 : 함수가 넘겨 받아야 할 값들.
  • type : 함수가 리턴하는 값의 데이터형.
  • 본체 : 함수가 호출되었을 때 수행될 코드.

인수

호출원에서 함수에게 넘겨주는 작업 대상.  전달받는 값이 없다면 void를 써 명시해 준다. 예전에는 형식 인수의 이름만 적고 본체가 시작되기 전에 이 인수들의 타입을 밝히기도 하였다.

return

타입으로 정해진 값을 리턴함과 동시에 함수를 종료한다. 값을 반환하지 않는 void형 함수도 종료를 위해 사용할 수 있다.

함수와 프로시저

함수는 특정 계산을 수행하며 리턴값이 있다. 반드시 수식내에서만 사용할 수 있으며 함수 단독으로 문장을 구성할 수 없다. 이 경우는 수학적 의미릐 함수와 거의 유사하다.

프로시저는 특정 작업을 수행하며 리턴값이 없다. 리턴값이 없기 때문에 수식 내에서는 사용할 수 없으며 단독으로 문장을 구성할 수는 있다. C의 void 함수가 해당한다.

다른 언어와 구분되는 C의 함수의 특징

  1. 함수끼리는 서로 평등한 관계에 있으며 상호 수평적이다.
  2. 리턴값은 있을 수도 있고 없을 수도 있다.
  3. 항상 단독으로 문장을 구성할 수 있다.
  4. 값에 의한 호출방식을 사용한다.

헤더 파일

함수의 원형

C는 1패스 방식으로 단 한 번 읽어서 번역을 하기 때문에, 사용되기 전에 컴파일러가 미리 그 형태를 알 수 있도록 원형을 선언한다. 미리 선언해 두면 본체가 어디에 있더라도 함수 호출부에서 이 명칭이 함수이고 어떤 인수를 요구한다는 것을 미리 알 수 있게 된다.

원형의 형식

type name (인수 목록);

으로 세미콜론을 붙여 끝낸다. 인수 목록에서 형식 인수명도 적어줄 수도 있고, 인수의 타입만 간략하게 밝힐 수도 있다. 읽는 사람을 위해 가급적이면 함수의 원형을 완전하게 적는 것이 더 권장된다.

헤더 파일

표준 함수 역시 함수이기에 사용되기 전에 선언되어야 한다. #include에 대해서는 뒤에서 설명할 것이다. 어떤 헤더에 어떤 함수가 선언되어 있는지는 인터넷에서 찾아볼 수 있다.

헤더 파일에 들어있는 것은 다음과 같다.

  1. 표준 함수의 원형
  2. 각 표준 함수들이 사용하는 매크로 상수들
  3. 각 표준 함수들이 사용하는 열거형 타입
  4. 자료의 가공을 간편하게 해 주는 매크로 함수들
  5. 구조체, 공용체 등 표준 함수가 요구하는 사용자 정의 타입의 정의

모듈

모듈 분할 컴파일

함수의 그룹 별로 모듈을 구성, 각 부를 구현하는 함수 집합에 대해 따로 만들어 개별적으로 컴파일해 하나의 실행 파일로 합치는 방식이다.

모듈 분할 컴파일의 장점

  1. 컴파일 속도가 빠르다
    함수들이 여러 개의 모듈에 분산되어 있으므로 한 함수를 수정한 경우 그 모듈만 컴파일 하면 된다. 잘게 나눌 수록 이 효율은 증대된다.
  2. 분담 작업이 가능하다.
    파일을 여럿으로 나누어 관리할 수 있으므로 가능하다.
  3. 프로젝트 관리가 쉽다
    모듈별로 관련 함수를 모아 놓았기 때문에 문제 부분을 찾아 수정하기 쉽다.
  4. 모듈을 재사용 할 수 잇다.
    기능적으로 독립되어 있는 집합이므로 후일 같은 기능을 구현해야 한다면 저비용으로 재사용이 가능하다.

함수의 호출 방식

값 호출

함수 호출 시 전달되는 대상이 실 인수 그 자체가 아니라 실인수의 값이다. 형식 인수가 함수 내에서 변경되더라도 실 인수에는 전혀 영향을 주지 않는다.

참조 호출

번지값을 넘겨받아 직접 실 인수로 작업을 수행한다. 참조 호출 함수의 실 일수로는 좌변값만 사용할 수 있다.

C++의 참조 호출

C는 포인터를 사용하며 참조 호출 흉내는 낸다. C++은 포인터를 이용하는 방법 외에 레퍼런스라는 개념으로 참조 호출을 추가로 지원한다. C언어의 참초 호출은 사실 엄밀한 의미의 참조 호출이 아니라 변수의 번지값을 넘겨받는다. C++의 레퍼런스도 엄밀히 따지면 값 호출이다.

전처리기

#include

#include 〈file.h〉

는 표준 헤더를 포함하고자 할 때 사용하고, 

#include "file.h"

는 사용자가 직접 작성한 헤더 파일을 포함시키고자 할때 사용한다. 사실 헤더의 검색 순위만 다를 뿐 바꿔써도 같은 이름의 다른 내용의 파일이 두 경로에 있지 않는 한 문제는 되지 않는다.

헤더가 아니더라도, 텍스트파일이기만 하면 다 포함할 수 있다. include하는 문서가 include한다면 그 문서도 include된다.

#define

#define 매크로명 실제값

소스의 모든 매크로명과 일치하는 부분을 찾아 실제값으로 치환한다. 같은 값을 반복해서 쓰기 힘들때 사용한다. 매크로는 중첩된다. 상수 뿐 아니라 함수 역시 치환해 사용할 수 있다. 여러 줄 일 경우 반드시 \를 뒤에 붙여 개행한다. 매크로는 단순하게 생각했을때와 결과가 다를 수 있으므로 사용에 주의해야 한다.

윈도우키를 조합한 단축키를 사용하지 않는 방법

윈도우키는 꽤나 유용해서 바로 실행 메뉴를 불러온다던가 검색을 띄운다던가, 좌우 창 배치를 빠르게 하는 등 컨트롤과 알트만큼 자주 쓰게 된다. 하지만 키보드가 좀 이상할 경우나 메트로 UI로 전환된다면 망하는 경우(…)에는 키를 통째로 뽑고 싶을 것이다. 불행히도 노트북을 쓴다면 윈도우 키를 뽑으면서 유상 서비스 예약을 하게 된다. 그러지는 말자.

  1. 윈도우 키를 사용하지 않기로 한다. 나는 윈도우키를 포기하겠다! 나는 윈도우키를 초월 하겠다!
    http://support.microsoft.com/kb/216893
  2. 그룹 정책 편집기를 사용한다. (gpedit.msc)
    1. 사용자 구성 – 관리 템플릿 – Windows 구성 요소 -파일 탐색기
    2. Windows+X 바로 가기 키 사용 안 함‘을 ‘사용함‘으로 설정
    3. 해제시에는 원 상태인 ‘구성 되지 않음’으로 설정

05. 연산자

연산자의 종류

기능별 종류 연산자
산술 연산자 + _ * / %
부호 연산자 + –
대입 연산자 = 복합 대입 연산자
관계 연산자 == != <= < >= >
증감 연산자 ++ —
포인터 연산자 * & []
구조체 연산자 . ->
논리 연산자 || && !
비트 연산자 ! & ~ >> <<
삼항 조건 연산자 ? :
쉼표 연산자 ,
sizeof 연산자 sizeof
캐스트 연산자 (type) type()
괄호 연산자 ()
C++ 연산자 new delete :: .* ->*

연산자의 우선 순위

순위 연산자 결합순서
1 () [] -> 왼쪽 우선
2 ! ~ ++ — + – (부호) * (포인터) & sizeof 캐스트 오른쪽 우선
3 *(곱셈) / % 왼쪽 우선
4 + – (덧셈, 뺄셈) 왼쪽 우선
5 << >> 왼쪽 우선
6 < <= > >= 왼쪽 우선
7 == != 왼쪽 우선
8 & 왼쪽 우선
9 ^ 왼쪽 우선
10 | 왼쪽 우선
11 && 왼쪽 우선
12 || 왼쪽 우선
13 ? : 오른쪽 우선
14 = 복합대입 오른쪽 우선
15 . 왼쪽 우선

연산자의 기능

산술 연산자

+ – * /

일반적인 사칙연산과 동일하게 덧셈, 뺼셈, 곱셈, 나눗셈을 수행한다. 각 셈에서 결과값은 타입을 벗어날 수 없음에 주의해야 한다.

%

나머지를 구하는 연산자.

대입 연산자

Assignment. 변수에 어떤 값을 집어넣는 동작. 우변에는 값을 구할 수 있는 식이라면 무엇이 와도 상관 없으나 좌변에는 좌변값만이 와야 한다. 대입 연산은 대입된 값을 리턴하므로 a=b=c=4등의 식도 성립 가능하다.

복합 대입 연산자

+, -, *, /, %, &, |, ^, <<, >>의 연산자 뒤에 결합해 좌변값을 대상으로 우변값을 연산하고 그 값을 좌변값에 바로 대입하도록 하는 식은 자주 활용된다.

증감 연산자

피연산자를 1씩 증가시키거나 감소시킨다.

전위형

증감 연산자가 피연산자 앞에 위치하고, 값을 먼저 증감시킨 후 그 결과를 리턴한다.

후위형

증감 연산자가 피연산자 뒤에 위치하고, 값을 먼저 리턴한 후 그 값을 증감시킨다.

주의점

피연산된 값은 상수이므로 증감연산자를 중복해 사용할 수 없다. 또한 한 식에서 여러번 사용할 때는 미리 값의 변화를 시험하고 사용하는 것이 좋다. 예로

printf(%d,%d\n",i,++i);

C는 함수의 인수를 뒤에서부터 순서대로 전달하므로 ++i가 먼저 수행된다. 그러나 인수 전달 순서는 지정되어 있지 않으므로 컴파일러마다 결과가 상이할 수 있다. 또한 가독성을 떨어뜨리므로 많이 사용하는 것은 자제해야 한다.

관계 연산자

수학에서와 같으며, ==는 동일한지, !=는 동일하지 않은지에 대해 0또는 1을 리턴한다. 논리값은 0은 거짓 그 외의 값은 모두 참으로 여긴다.

상등 연산자의 사용

==를 사용할때는 오타로 인한 버그를 줄이기 위해 상수를 좌변에 써주는 것이 좋다.

논리 연산자

  • ! : 논리식의 값을 반대로 만든다.
  • && : 두 식이 모두 참일때만 참이다.
  • || : 두 식이 모두 거짓일때만 거짓이다.

&&과 ||의 경우, 좌측에서부터 시작해 논리값이 정해진다면 그 이후는 수행하지 않는다.

비트 연산자

  • ~ : 비트를 반전시킨다
  • & : 같은 자리의 두 비트가 모두 1이면 1이 된다.
  • | :같은 자리의 두 비트가 모두 0이면 0이 된다.
  • ^ : 같은 자리의 두 비트가 달라야 1이 된다.
  • << : 지정한 수만큼 왼쪽으로 비트를 이동한다.
  • >> : 지정한 수만큼 오른쪽으로 비트를 이동한다.

&의 활용

비트마스크에서 해당되는 부분만 1로 하고 연산을 수행해, 그 값을 추출할 수 있다.

^의 활용

XOR로, 같은 값에 재연산을 하면 원래대로 돌아오는 특성 덕에 기초적인 암호화나 이미지의 이동, 반복적인 점멸 처리등에 사용한다.

쉬프트 연산자

빈 자리는 0으로 채워진다. 고속의 그래픽 처리가 필요할 때 사용된다. 주로 부호없는 정수형을 대상으로 하며 실수형은 안된다. 부호있는 정수형은 동작이 달라지므로 권장하지 않는다.

2^n이 되는 것을 이용하여 조합을 이용해 곱셈을 수행한다. CPU는 가산기이므로 곱셈과 나눗셈은 비용이 높은 계산식이므로 더 경제적이다. (나머지 연산자는 더 비용이 높다.)

회전 연산

연산자 형태로는 제공되지 않고, 함수 형태로 제공된다. 쉬프트 연산자와 유사하게 _rotl은 왼쪽으로, _rotr은 오른쪽으로 쉬프트하나 공백을 소실되는 비트로 채워넣는다.

rotl(bitmask, bitToRotate),rotr(bitmask, bitToRotate)

삼항 조건 연산자

매우 간단한 if 구문 대체자. 가동성을 위해 조건식에는 괄호를 사용하는 것을 권장한다.

조건식 ? 참일 경우 리턴 : 거짓일 경우 리턴

쉼표 연산자

좌변을 먼저 평가하고 우변을 평가한 후 우변의 연산 결과를 리턴한다.

{ }

의 도움 없이 두개 이상의 문장을 하나로 묶어야 할 때와 for문에서 제어 변수 두 개를 사용하고자 할때 중요하게 쓰인다.

sizeof 연산자

단순한 변수나 배열까지는 왜쓰나 싶지만, 구조체와 같은 경우나 소스 수정이 이어졌을때 크기가 변할 수 있는 경우에 매우 유용하게 쓰인다.

컴파일 시에 컴파일러에 의해 계산되며 그 결과는 정수 상수이다. 타입이나 변수의 크기는 컴파일할 때 미리 알 수 있기 때문에 컴파일러가 컴파일할 때 계산해서 결과 상수를 대신 집어 넣는다. (실행 시간에 계산되지 않는다.)

캐스트 연산자

수식 내에서 변수의 타입을 강제로 다른 타입으로 바꾼다. 수식 내에서 변수의 타입을 임시로 바꾸는 것이지 변수의 타입 자체를 바꾸는 것은 아니다.

  • C style casting : (type) variable
  • C++ style casting : type (variable)

04. 제어문

조건식

==, !=, >, <, <=, >=를 이용한 비교연산자는 참일 경우 1을 리턴한다. 0은 거짓과 같으며 0이외의 다른 모든 수, 혹은 그들을 리턴하는 수식은 참의 값을 갖는다. 식1&&식2의 경우, 순차적으로 계산하므로 식1이 거짓이면 식2는 계산하지 않아 경제성을 노려볼 수 있다.

조건문인 제어문

if()

가장 기본적인 것으로 괄호안이 참일 경우 후에 올 구문, 혹은 블록을 수행한다.

else()

가장 마지막의 if가 거짓일 경우 후에 올 구문, 혹은 블록을 수행한다.

else if()

가장 마지막의 if가 거짓일 경우에 괄호안이 참일 경우 후에 올 구문, 혹은 블록을 수행한다.

식1?식2:식3

식1이 참이면 식2의 값을, 거짓이면 식3의 값을 리턴하는 if..else의 inline판이다.

switch..case

변수를 받아 블록내의 case와 일치하면 해당 블록을 수행한다.

for(식1;식2;식3)

식1이 실행되고, 식2가 참이면 후에 올 구문 혹은 블록을 수행한다. 수행 한 후 식3을 수행한 뒤 식2의 검사단계로 돌아간다.

while()

괄호안이 참인지 확인한 뒤 수행한다. 수행이 끝나면 괄호 안의 값이 참인지 확인하는 단계로 돌아간다.

do…while

참 거짓에 관계없이 do 이후의 내용을 한번 수행한 뒤 참인지 확인한다. while에서 순서만 한번 바뀐 것.

조건문이 아닌 제어문

goto

코드의 물리적인 위치로 이동하게 하므로 논리적인 흐름에 따라 코딩해야 하는 입장에서는 부적절하다.

continue

현재 속해있는 가장 가까운 루프의 다음 단계로 넘어간다.

break

현재 속해있는 가장 가까운 루프를 종료한다.

03. 변수

변수의 정의

단어적 정의

변할 수 있는 수. 고정되어 있지 않은 수. 이름은 ‘수’이지만 반드시 수치값만 저장되는 것은 아니며 문자열이나 포인터 같은 좀 더 복잡한 값도 저장될 수 있다. number가 아닌 data(값)

변수와 메모리

메모리는 주 기억 장치이다. 컴퓨터가 하는 주된 일은 메모리에 값을 기록하고, 메모리에서 값을 읽는 일이다. 여러가지 복잡한 일들은 여러 단계의 메모리 읽기 쓰기, 연산이 반복된 결과이다.

모든 작업에 메모리 값을 읽고 써야 하기에 만약 변수가 없다면 사용자는 PAM(Physical Address Map)을 통째로 외워야 할 것이다. 그래서 컴파일러는 변수가 실제 어떤 번지를 가리키는 지 기억하고 있다가 변수를 사용하면 실제 번지에 값을 읽거나 쓰는 코드를 대신 작정한다.

변수 이름의 제한

  1. 길이 : 제한 없음.
  2. 문자 : alphanumeric characters (대소문자를 구분함) + _

실제 제한은 아니나 권고 사항은 다음과 같다.

  1. 임의의 문자가 아닌 의미를 설명하는 이름을 쓸 것.
  2. 길이에 제한이 없다고 너무 길게 쓰지 않을 것.
  3. 대소문자 구성을 일관되게 할 것.

변수명을 잘못 기입하는 일을 줄일 수 있을 것이다.

변수의 종류

  1.  기본형
    1. 정수형
      1. 문자형 (1 byte)
        1. signed char : -128~127
        2. unsigned char :0~255
      2. 정수형
        1. short, short int, signed short, signed short int : -32767~+32767 을 포함하는 범위. 16비트 이상.
        2. unsigned short, unsigned short int : short와 같지만 부호 없음.
        3. int, signed int :
        4. unsigned int : int와 같지만 부호 없음.
        5. long, long int : −2147483647~+2147483647을 포함하는 범위. 32비트 이상.
        6. unsigned long, unsigned long int : long과 같지만 부호 없음.
        7. long long, long long int : −9223372036854775807~+9223372036854775807을 포함, 64비트 이상.
        8. unsigned long long, unsigned long long int : long long과 같지만 부호 없음.
      3. 열거형
        1. 사용할 수 있는 값을 열거해 놓은 것으로 내부적으로 정수형으로 처리 됨.
        2. 그 크기는 int value까지만 보장됨.
    2.  실수형
      1. float
        1. 부호 1비트, 지수부 8비트, 가수부 23비트의 4바이트 크기.
        2. 유효 자리수는 7자리이나 실제로 신뢰할 수 있는 것은 소숫점 아래 6번째 자리까지. (이것도 불안할 경우가 있다.)
      2. double
        1. 부호 1비트, 지수부 11비트, 가수부 52비트의 8바이트 크기.
        2. 유효 자리수는 15자리이나 역시 실제로 신뢰할 수 있는 것은 더 짧음.
      3. long double
        1. 부호 1비트, 지수부 15비트, 가수부 112비트의 16바이트 크기.
        2. 33~36개의 자리수를 제공하나 믿을 수 없음.
  2. 유도형
    1. 배열
      • 연속적인 공간의 같은 타입 n개 집합.
    2. 구조체
      • 배열과 달리 서로 다른 타입의 집합.
    3. 포인터
      • 메모리 번지를 저장.
    4. 사용자 정의형
      • 사용자가 마음대로 저장.

변수의 선언

타입 변수명1(=초기값1),변수명2(=초기값2),…,변수명n(=초기값n);

printf

서식 문자열

  1.  %d, %i
    • 10진수
  2. %u
    • 부호 없는 10진수
  3. %o
    • 부호없는 8진수
  4. %x, %X
    • 16진수
    • x는 A~F를 소문자로 출력. X는 대문자로 출력.
  5. %f
    • 고정 소수점으로 double을 출력
  6. %e, %E
    • 부동 소수점으로 double을 출력
    • e는 지수부 표시를 소문자 e로 출력. E는 대문자 E로 출력
  7. %g, %G
    • %e, %f중 더 짧은 형식으로 출력.
    • g,G는 e,E에 대응 (출력에 해당될 경우)
  8. %s
    • 마지막에 null캐릭터가 있는 배열(문자열)
  9. %c
    • char
  10. %p
    • 포인터
  11. %a/%A
    • 16진수 double
  12. %n
    • 출력된 문자의 숫자
  13. %%
    • 문자 %

정렬해서 출력

서식 문자열에 음수나 양수을 붙여 가지런히 정렬해 출력할 수 있다. 음수를 붙이면 지정한 숫자에 맞춰 오른쪽에 공백이나 0을 추가하고, 양수일 경우 반대 방향에 추가한다. 데이터가 지정한 길이보다 길면 자르지 않고 원래 길이대로 출력된다. (정렬을 위해 선처리 필요.) 소숫점을 출력하는 형식에서는 지정한 자리수에서 반올림을 하도록 ‘.’뒤에 숫자를 넣어 소숫점 이하 자릿수를 제한할 수 있다.

02. 작성

IDE

요즘은 IDE가 워낙에 잘 나와 있기 때문에, IDE님과 컴파일러님의 말씀만 잘 귀담아 들으면 빌드는 문제없다.

컴파일러님이 조금 화나셨을 때 하는 말씀이 warning으로, 인간이 잘못한 것 같은 삘을 내뿜는다는 뜻이다. error는 인간이 해놓은 것에 맞춰주지 못하겠으니 다시 해오라는 뜻이다. 모쪼록 잘 대처해야 하나 warning과 error의 수위는 같은 코드라도 환경에 따라 다를 수 있다.

프로젝트

하나의 실행 파일을 제작하는데 필요한 관련 파일들의 집합. 코드의 소스 파일 외에도 그림, 소리, 폰트 등을 모두 묶어 놓은 것이다. 프로젝트는 보통 한 디렉토리에 저장되므로 프로젝트의 위치를 통째로 옮기거나 백업본을 만들기 좋다.

솔루션

프로젝트보다 더 상위의 개념. 여러 개의 프로젝트를 모아 놓은 것이다. 프로젝트는 실행 파일 하나를 만들기 위한 구성 파일의 집합이며 이런 프로젝트 여러 개가 모여 하나의 솔루션을 구성한다. 보통 한 제품은 여러 개의 실행 파일로 구성되므로 솔루션은 제품 하나라고 할 수 있다.

프로그램의 구성 요소

키워드는 언어에서 예약된 단어들로 함부로 인간이 사용해서는 안된다. 명칭은 인간이 붙이는 것으로 예약어에 없고, 길이 제한과 형식 제한을 벗어나지 않는다면 마음껏 지어도 좋다. 상수는 변화하지 않는 값이고 변수는 변화할 수 있는 값이다. 연산자는 미리 정의된 규칙에 따라 계산을 수행할 것을 지시한다. 구두점은 단어들을 구분하고 뜻을 명확하게 하는 공백이 아닌 문자이다. 나머지는 공백문자와 주석이다.

키워드

C의 경우 다음과 같다.

auto, case, cdecl, const, char, continue, default, do, double, else, enum, extern, float, for, goto, if, int, long, register, return, short, signed, sizeof, static, struct, switch, typedef, union, unsigned, void, volatile, while

C++의 키워드는 다음과 같다.

alignas, alignof, and, and_eq, asm, auto, bitand, bitor, bool, break, case, catch, char, char16_t, char32_t, class, compl, const, constexpr, const_cast, continue, decltype, default, delete, do, double, dynamic_cast, else, enum, explicit, export, extern, false, final, float, for, friend, goto, if, inline, int, long, mutable, namespace, new, noexcept, not, not_eq, nullptr, operator, or, or_eq, override, private, protected, public, register, reinterpret_cast, return, short, signed, sizeof, static, static_assert, static_cast, struct, switch, template, this, thread_local, throw, true, try, typedef, typeid, typename, union, unsigned, using, virtual, void, volatile, wchar_t, while, xor, xor_eq

명칭

사용자가 직접 만들어서 사용하는 것이다. 제약 사항은 다음과 같다.

  1. 키워드는 사용 불가.
  2. 알파벳, 숫자, 밑줄기호로 구성.
  3. 첫 문자는 알파벳이나 밑줄기호만 올 수 있다.
  4. 대소문자를 구분한다.

상수

변수의 반대되는 개념으로 고정된 값을 가지는 식. 숫자 외에 문자, 문자열도 상수로 존재한다. 문자열은 홑따옴표로 감싸 표현하는데, 이는 곁따옴표는 맨 뒤에 널 문자가 오는 최소 2바이트 문자열이기 때문이다.

연산자

계산을 지시하는 기로들이다. 사칙 연산자 외에 관계, 대입, 논리 연산자가 있다. 포인터 연산자, 삼항 연산자 등 나름대로 복잡한 연산자들도 있다. (5장에서 자세히 다룬다.)

구두점

자연어의 구두점과 마찬가지로 쉼표, 따옴표, 괄호, 세미콜론 등의 문자가 구두점의 역할을 한다.

공백 문자

스페이스, 탭, 개행 코드 등이 공백이다. 눈에 보이지 않지만 구성 요소들을 구분하는 아주 중요한 역할을 한다. 주석도 일종의 공백으로 인정된다.

주석

설명을 위해 삽입되는 문자열이다. 한 줄 내에서만 주석을 쓰고 싶을 때는

//

를 사용한다. 여러 줄을 주석 처리 할 때는

/* */

을 사용한다. 예전 컴파일러 중에는 한 줄 주석을 지원하지 않는 경우도 있다. 설명을 달아 놓는 용도 외에도 코드를 임시적으로 사용하지 않도록 할 때에도 사용된다. (comment out)

01. 프로그래밍

프로그래밍이란 무엇인가?

프로그램을 만드는 것. 프로그램은 명령의 집합이다. 명령에는 결과가 따른다. 프로그래머는 오더에 맞게 결과가 나오도록 한다. 이는 목적을 명확히 하고 적절한 도구를 사용해 논리적으로 작성하는 것으로 수행된다.

목적을 명확히 한다.

요구 사항이 있다고 해도 이는 프로그램의 목적과 차이가 날 수 있다. 혹은 내/외부적인 이유로 구현가능하지 않을 수 있다. 이후 구현에서도 무엇을 하고 있는지 확실히 하지 않으면 코드가 꼬이게 되어있다. 그러므로 코드의 스키마가 잡혀있어야 한다. (이는 주석 처리를 통해 확실히 하는 것이 좋다.) 마지막으로 완성된 코드에 있어서, 좋은 코드인가 아닌가는 주어진 조건에 따라 다르다. 이에 따라 코드 평가의 단계에서도 목적을 명확히 할 필요가 있다.

논리적인 수행이란 무엇인가?

언어는 문법과 작문으로 이루어지는데 이 과정을 철저히 하는 것을 의미한다.

왜 C/C++를 배우는가?

비록 C는 분류로는 절차지향 언어지만, 두 언어는 멀티 패러다임 언어라 부를 수 있을 정도로 사용자의 능력 만큼 자유롭게 구현이 가능하다. 문법이 간결하며 대부분의 언어가 C의 문법을 기반으로 하고 있으므로 다른 언어의 학습에도 도움이 된다. 운영체제를 만들 수 있는 언어로, 로우레벨의 접근이 가능해 컴파일러가 있다면 만들 수 없는 프로그램이 없고 능력만큼 고효율의 프로그램을 작성할 수 있다.

C의 표준

ANSI C가 표준이다. 최신의 표준안은 C11로 draft를 이곳에서 확인할 수 있다. (ANSI에서 정식본으로 보려면 C와 C++ 각각 60불을 지불해야 한다.)

ANSI C와 클래식 C의 차이

  1. 표준 라이브러리 함수를 규격화했으며 헤더 파일도 통일했다.
  2. 함수의 원형 선언 기능이 추가되어 컴파일러가 함수 호출부에서 타입 체크를 할 수 있다.
  3. 정수, 실수 상수의 타입을 지정할 수 있는 L,U,F 등의 접미어가 추가되었다.
  4. enum, void형과 const,volatile 제한자가 추가되었다.
  5. 인접 문자열 상수를 합쳐 주고 확장열의 기능도 추가되었다.
  6. 함수 내부에서 선언하는 지역 배열이나 구조체를 초기화할 수 있다.
  7. 구조체끼리 대입할 경우 구조체 크기만큼 메모리 복사를 한다.

컴파일러

인간의 언어에 가까운 고수준의 언어인 소스 파일을 저수준 언어인 어셈블리어나 기계어로 바꿔주는 프로그램이다. c컴파일러는 object파일을 생성 후 link의 과정을 거쳐 실행 파일을 형성한다. 이를 build라 한다.

교체한 예전 하드에서 레지스트리 값을 가져오기

드물지만 예기치 않은 사유로 인해 하드를 교체하게 되었을 때, 예전 레지스트리의 값이 필요할 때가 있다. Putty의 세션 정보라던가, CD key일 수도 있다. 윈도우 7이상에서는 사용자별로 레지스트리를 NTUSER.DAT로 저장해둔다. 다른 부분도 System32\Config에 저장되어있다.

결국 파일 형태로 저장되므로 이 파일들을 구할 수 있다면 현재 사용 중인 윈도우의 레지스트리 편집기에서 하이브 불러오기해 열어보고 필요한 부분을 찾아 사용할 수 있다.

Largest prime factor

문제

가장 큰 소인수를 구하라.

이번 문제 역시 6008억 정도로 숫자가 작으므로 특별한 방법을 필요로 하지 않는다.
기본적인 방법을 두가지 생각해보면

  • 방법 1 : 숫자의 제곱근에서 시작해 소수의 목록을 얻은 뒤 가장 큰 소수부터 나누어 떨어지는지 살펴본다.
  • 방법 2 : 2부터 시작해 소수로 더 이상 나누어 떨어지지 않을 때까지 나누고 몫이 1이 되면 그 소수의 값을 반환한다.

만약 64비트 정수를 지원하지 않는 플랫폼이라면 직접 만들어 주고 쓸 연산자로 오버로드 하겠지만 .. 있는데 굳이 사서 고생할 필요는 없겠다.

방법 1의 경우 2~숫자의 제곱근까지 체를 쓰든 뭘 하든 소수 목록을 얻는다. 방법 2에서 2 이후의 숫자가 소수인지 확인하는 것은 하지 않아도 되지만 본능적으로 소수인지 확인하고 싶어지는 것은 어쩔 수 없다. 둘다 소수 목록으로 해결한다고 해도, 운에 의한 1보다는 2에 눈이 간다. 하지만 특정 소인수를 많이 포함하는 경우에는 나눗셈 연산을 여러번 하게되니 어차피 도찐 개찐. 숫자가 매우 커서 사용자 정의형을 사용하는 경우라면 클래식 자료형 이하로 숫자가 줄어드는 편이 오버헤드 줄이기에 좋을테니 또 모르겠다.