본문 바로가기

C언어 다시 다지기

C의 기본적 지식(1)




▶ 공백계 문자의 취급

  C 프로그램에서 공백문자는 확대 해석된다. 말하자면


  블랭크문자    탭문자    쪽 넘김    개행문자


와 같은 것은 모두 넓은 의미에서 공백문자로 취급된다. 공백문자가 여러 개 연속되어 있어도 1개의 공백과 같은 기능을 한다. C에서는 개행문자를 단순한 공백과 동일시함으로써 행의 개념을 없앤다. 


▶ 행의 끝

파일 상에서 행의 끝은 개행문자로 표현된다. 그러나 C컴파일러는 이 개행문자를 단순한 공백으로 간주하므로 C에서는

- 그 행의 끝까지 유효

한 처리는 없다. 예를 들어 주석문도

- 그 행의 끝까지 주석문

으로 삼는 규칙은 없다. 어디까지나 주석문의 시작에서 주석문의 끝까지가 유효 범위인 것이다. 주석문이 여러 행에 걸쳐 있을 수도 있다.

  단 C에도  행의 끝을 인식하는 기능히 하나 있는데, 그것이 바로 프리프로세서 명령이다. #define을 비롯한 프리프로세서는 '행의 끝까지'를 하나의 명령문으로 인식한다.


▶ 행의 연결(종단문자의 무효화)

 프리프로세서는 행의 끝까지를 하나의 문장으로 판단하기 때문에 C의 본문과 같이 자유롭게 행을 나눌 수 없다. 프리프로세서에서는 2행에 걸쳐 쓸 수 없게 되어 있다. 그러나 행 끝에 '\'를 써넣음으로써 행을 나눌 수도 있다.


표준 장석법                    #define beep( ) putchar(7);

'\'에 의한 행 나누기         #define beep( ) put\

                       char(7);


위의 두 가지 방법은 동일한 작용을 한다. 여기서는

 -행 끝에 '\'가 있으면 그 '\' 자식과 이어지는 개행문자를 없는 것으로 간주

함으로써 2행을 1행으로 병합시킨다. 이 작업은 컴파일러가(엄밀하게 말하면 프리프로세서가)소스 프로그램을 읽어서 맨 처음에 처리한 후 컴파일한다. 이 때 개행한 후 공백문자들도 의미를 갖게 되므로 주의해야 한다. 예를 들어


#define beep( ) put\

        char(7);       ...앞의 공백문자들도 의미가 있으므로 에러


라고 하면 에러가 된다.

  이 규칙은 프로 프로세세의 기술을 보다 유연하게 만들기 위해 고안된 것이며, 모든 C소스 프로그램 안에서 적용할 수 있다. C에서는 기본적으로 행 나누기를 자유롭게 할 수 있다. 하지만 한 가지의 경우는 주의해야 하는데, '토큰을 끊고 행 나누기' 하는 것이 그것이다. 이 때 '\'를 이용하면 '토큰을 끊고 행나누기'를 할 수 있게 된다.


▶ 토큰

 토큰은 C프로그램 해석 상의 의미있는 문자 또는 문자열을 뜻한다. 실제로는


연산자    * / + - ...

분리자    ( ) { } [ ] , ; :

식별자   변수명이나 함수명 등

예약어   if for long ...

정수      100 12.345 0xff3a 'a' "abcde"


로 구성된다. 예를 들어

a = dt[pos]+100;

라는 문장은

a = dt [ pos ] + 100;

라는 토큰으로 식별된다.


▶ 특수문자의 역할

C에서는  다양한 특수문자(도형문자)를 이용한다. 다음은 특수문자와 그 용도(의미)이다.


문자 

     용도

 !

 관계 연산 논리 부정

 "

 문자열 정수 

 #

 프리프로세서 

 $ 

 사용하지 않음

 %

 나머지 서식 지정

 &

 논리적 비트AND 포인터 연산

 '

 문자정수 

 (

 함수 우선순위 설정 

 )

 함수 우선순위 설정 

 *

 곱셈 포인터 연산 

 +

 +부호 덧셈 증가 

 ,

 콤마 연산 

 -

 -부호 뺄셈 감소 멤버참조 연산 

 . 

 멤버참조 연산 소수점 

 / 

 나눗셈 

 :

 조건 연산

 ;

 문장의 끝

 <

 관계 연산 비트 쉬프트

 =

 관계 연산 대입

 >

 관계 연산 비트 쉬프트 멤버참조 연산

 ?

 조건 연산

 @

 사용하지 않음

 [

 배열

 \

 이스케이프문자 행 연결

 ]

 배열

 ^

 비트XOR

 _

 식별자

 {

 복합문

 |

 논리화 비트 OR

 }

 복합문

 ~

 비트반전(1의 보수)


▶ 대문자와 소문자의 구별

  C에서는 대문자와 소문자가 구별된다. 예를 들어

  int data, DATA, Data;

라는 선언을 했을 때 3개의 변수는 서로 전혀 관계없는 독립된 것으로서 작동한다.


▶ 문자열 정수의 연결

  서로 이웃한 문자열 정수는 연결할 수 있다. 예를 들어

  

 "abc" "def" 

  

  라는 문자열은

  

 "abcdef"

  

  와 동일하다. 이 기능을 이용하면 너무 긴 printf문을 문자열의 중간에서 개행할  수도 있다. 예를 들어

  printf("abc\n"

              "def\n"

              "ghi\n");


와 같이 쓸수도 있다. 이 문자열의 배치는 화면 출력 이미지와 일치시키기 위해 유효하다.


▶ 오브젝트

  오브젝트라는 용어는 광범위하게 쓰이고 있다. 예를 들어 '오브젝트 코드'라고 하면 기계어의 형식이 된 코드를 말한다. 언어시스템이 세계에서는 보다 한정된 의미를 갖게 되는데 단순히 오브젝트라고 할 때는

  - 데이터를 입력하거나 그 데이터를 참조할 수 있는 이름이 있는 기억 영역

을 가리킨다. 단 const오브젝트에는 입력할 수가 없다. 오브젝트가 있는 장소를 주소라고 하며 오브젝트를 식별하는 이름이 변수이다.

 또한 C를 기능 강화한 C++의 세계에서는 단순히 오브젝트라고 칭했을 때 '클래스 오브젝트'를 의미할 수도 있다.


▶ 오퍼레이터와 오퍼랜드

  오퍼레이터(operator : 연산자)는 연산을 지시하는 것이다. 오퍼레이터보다는 '연산자'라는 용어가 보다 보편적으로 쓰인다. 이에 대응하는 말이 오퍼랜드(operand : 작용 대상)로서 연산의 대상이 되는 것을 뜻한다. 예를 들어

a+2

라는  식이 있을 때 +는 오퍼레이터, a와 2는 오퍼랜드이다.


▶ 단항과 이항

  단항은 오퍼랜드가 하나라는 것을 의미한다. 1항이면 단항, 2항이 있으면 이항이라고 한다. 이와 관련하여 다음과 같은 용어를 알아두자.


단항식

  연산자와 하나의 오퍼랜드로 구성되는 다음과 같은 식을 말한다.

  &a

  !a

  sizeof a


단항 연산자

  하나의 오퍼랜드를 연산 대상으로 하는 연산자. 예를 들어

  &p

  b--

  ++c

 안의 &, --, ++은 단항 연산자이다.


이항 연산자

  2개의 오퍼랜드를 연산 대상으로 하는 연산자, 예를 들어

  a*b

  a/b

안의 *, / 는 이항 연산자이다.


▶ 좌변값과 우변값

  좌변값과 우변값에서 방향은 기본적으로 대입기호 '='에 대해 어느 쪽에 위치하는지를 나타낸다. 좌변값과 우변값은 다음과 같은  의미를 갖고 있다.


좌변값

  오브젝트를 참조하거나 변경하는 식 또는 그 식에서 계산한 결과, 대입식의 좌변에(우변에도) 쓸 수 있다.


우변값

  값을 참조할 수는 있으나 변경할 수 없는 식. 대입식의 우변에는 쓸 수 있지만 좌변에는 쓸 수 없다.

  예를 들어 다음과 같이 썻다고 하자.

  #define DATA 100

  int a, b[10];

  int *p;

  여기서 좌변값은 a,b[], p이고 우변값은 DATA, b이다. 좌변값은 우변에도 쓸 수 있으나 우변값은 좌변에 쓸 수 없다. 예를 들어 b[3]은

   b[3]=100;

라고 쓸 수 있으므로 좌변값이다. 이에 대해 배열명 b자체는

   p = b;

라고 쓸 수 있으나

   b=...;

라고 쓸 수는 없으므로 우변값이다. 또한 ++ 연산자는 그 대상 오브젝트가 좌변값이어야 한다. 따라서

   ++a;

라고 쓸 수는 있지만

  ++DATA;

라고 쓸 수는 없다. const형 수식자를 사용한 변수도 우변값이 되는데 이유는 그 값을 변경할 수 없기(좌변에는 쓸 수 없음)때문이다.


▶ EOF와 NULL

  EOF와 NULL은 데이터의 끝을 검출할 때 자주 쓰인다.

 while((c=getchar()) != EOF) {

       ...

 }


 while(gets(st) != NULL) {

      ...

 } 


  이 2개의 기호정수는 stdio.h 안에서

  #define EOF (-1)

 #define NULL (0)

으로 정의되어 있다. NULL은 환경에 따라 OL이 되거나

  #define NULL ((void *)0)

이 될 때도 있다. 어쨌든 프로그래머가 기호정수의 값을 기억해 둘 필요는 없으며 프로그램의 맨 앞에

  #include <stdio.h>

라고 쓰면 이 값을 이용할 수 있다. 그리고

  - getchar는 입력 종료로 EOF를 리턴한다.

  - gers는 입력 종료로 NULL을 리턴한다.

  - fopen은 오픈 실패로 NULL을 리턴한다.

와 같은 약속을 알아두면 된다. 어떤 함수가 EOF, NULL에 대응하는지에 대해서는 메뉴얼의 라이브러리 함수의 설명 부분에 게재되어 있다.


'C언어 다시 다지기' 카테고리의 다른 글

DAY004 변수의 초기화  (0) 2018.04.30
DAY003 변수의 선언  (0) 2018.04.30
DAY002 숫자를 저장하는 변수  (0) 2018.04.26
DAY001 변수란?  (0) 2018.04.17
C의 기본적 지식(2)  (0) 2018.03.14