'컴퓨터 언어/C'에 해당되는 글 18건

  1. 2013.03.05 pThread를 이용한 Thread by 똘이 임덕규
  2. 2013.02.25 Static 변수 by 똘이 임덕규
  3. 2013.01.16 메세지 기법 by 똘이 임덕규
  4. 2012.12.20 배열의 이름은 첫번째 원소의 주소이다. by 똘이 임덕규
  5. 2012.06.11 문자열, 그것은 배열. by 똘이 임덕규 (2)
  6. 2012.06.10 Makefile을 작성하자. by 똘이 임덕규 (2)
  7. 2012.06.10 다수의 소스 컴파일을 도와줄 Make by 똘이 임덕규 (2)
  8. 2012.06.09 ASCII Code는? by 똘이 임덕규 (1)
  9. 2012.06.09 자료형 by 똘이 임덕규 (1)
  10. 2012.06.08 어휘적 최소 단위 "토큰" by 똘이 임덕규 (1)

C에서 Thread를 구현하기 위해서는 pthread.h 함수를 사용해야 한다. 


기본적인 Thread 함수

pthread_create

int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);
  • 쓰레드 생성을 위해서 사용 
  • 첫번째 인자인 thread 는 쓰레드가 성공적으로 생성되었을때 생성된 쓰레드를 식별하기 위해서 사용되는 쓰레드 식별자 
  • 두번째 인자인 attr 은 쓰레드 특성을 지정하기 위해서 사용, 기본 쓰레드 특성을 이용하고자 할경우에 NULL 을 사용 
  • 세번째 인자인 start_routine는 분기시켜서 실행할 쓰레드 함수
  • 네번째 인자는 쓰레드 함수의 인자
  • 리턴값은 성공시 0, 실패시 0 이상의 수

예제 example_1.c

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

/* 쓰레드 함수 */
void *t_function(void *data)
{
    int id;
    int i = 0;

    id = *((int *)data);

    while(1)
    {
        printf("%d : %d\n", id, i);
        i++;
        sleep(1);
    }

    return;
}

int main()
{
    pthread_t p_thread[2];

    int thr_id;
    int status;
    int a = 1;
    int b = 2;

    /* 쓰레드 생성 인자로 1을 넘긴다 */
    thr_id = pthread_create(&p_thread[0], NULL, t_function, (void *)&a);
    if(0 < thr_id)
    {
        perror("thread create error : ");
        exit(0);
    }

    /* 쓰레드 생성 인자로 2를 넘긴다 */
    thr_id = pthread_create(&p_thread[1], NULL, t_function, (void *)&b);
    if(0 < thr_id)
    {
        perror("thread create error : ");
        exit(0);
    }

    /* 쓰레드 종료를 기다린다
     * 실행된 쓰레드에 대해서는 pthread_join 등의 함수를 이용하여 쓰레드가 종료될 때까지 기다려 주어야 한다.
     * pthread_join은 일종의 fork의 wait과 비슷하게 작동하며, 쓰레드 자원을 해제 시켜준다.*/
    
    pthread_join(p_thread[0], (void **)&status);
    pthread_join(p_thread[1], (void **)&status);
    
    return 0;
}


저작자 표시
신고

'컴퓨터 언어 > C' 카테고리의 다른 글

pThread를 이용한 Thread  (0) 2013.03.05
Static 변수  (0) 2013.02.25
메세지 기법  (0) 2013.01.16
배열의 이름은 첫번째 원소의 주소이다.  (0) 2012.12.20
문자열, 그것은 배열.  (2) 2012.06.11
Makefile을 작성하자.  (2) 2012.06.10

Static 변수의 특징

  • 다른 변수와 마찬가지로 해당하는 가장 윗 부분에 선언된다.
  • 전역 변수 처럼 '0' 으로 초기화 된다.
  • 함수가 끝나도 해당 값이 파괴되지 않는다.
  • 저장되는 메모리 영역은 전역 변수가 저장되는 정적 데이터 영역
  • 지역변수와 마찬가지로 해당 함수 안에서만 사용이 가능하다.

Static 변수의 특징을 잘 알아볼 수 있는 예제를 이용하여 정확히 파악

#include <stdio.h>

void printCount(void);

int main(void)
{
    int i;

    for(i = 0; 10 >= i; i++)
    {
        printCount();
    }
    
    return 0;
}

void printCount(void)
{
    static int i;

    printf("%d\n", i);
    i = i + 1;
    
    return;
}

함수 printCount 안의 변수인 i는 함수가 종료되어도 파괴되지 않고 값을 유지하고 있다. 



전역변수에서 static을 선언해 주면 다른 파일에서 해당 변수를 extern으로 건다해도 참조 할 수 없다.


저작자 표시
신고

'컴퓨터 언어 > C' 카테고리의 다른 글

pThread를 이용한 Thread  (0) 2013.03.05
Static 변수  (0) 2013.02.25
메세지 기법  (0) 2013.01.16
배열의 이름은 첫번째 원소의 주소이다.  (0) 2012.12.20
문자열, 그것은 배열.  (2) 2012.06.11
Makefile을 작성하자.  (2) 2012.06.10

함수포인터를 이용한 유용한 기법중 하나인 “메세지 기법”에 대하서 정리했다.

struct MFT_Entry_Attribute_Type
{
    unsigned short	usNum;
    const char *	cDes;
    void (*fp)(void *);
} MFT_Attr_Type[] = {
    { 16, "$STANDARD_INFORMATION", Content_STD_INFO}
    ,{ 32, "$ATTRIBUTE_LIST",0}
    ,{ 48, "$FILE_NAME",Content_FILE_NAME}
    ,{ 64, "$VOLUME_VERSION or $OBJECT_ID",0}
    ,{ 80, "$SECURITY_DESCRIPTOR",0}
    ,{ 96, "$VOLUME_NAME",0}
    ,{112, "$VOLUME_INFORMATION",0}
    ,{128, "$DATA",0}
    ,{144, "$INDEX_ROOT",0}
    ,{160, "$INDEX_ALLOCATION",0}
    ,{176, "$BITMAP",0}
    ,{192, "$SYMBOLICK_LINK or REPARSE_POINT",0}
    ,{208, "$EA_INFORMATION",0}
    ,{224, "$EA",0}
    ,{256, "$LOGGED_UTILITY_STREAM",0}
    ,{257, "Unknown",0}
};
MFT_Entry_Attribute_Type 구조체는
  • 직접적인 비교에 쓰일 변수 한 개와
  • 메세지 출력을 위한 const char * 형의 변수 한 개,
  • 필요에 따라 함수를 호출할 수 있도록 함수 포인터 선언

으로 이루어져 있으며 소스에서 보는 바와 같이 구조체 선언과 동시에 구조체 배열 변수를 선언해 두었다.


이것을 어떻게 사용하는지 아래 소스에서 살펴보면,

void * test(void *p)            /* 213 페이지 */
{
    struct MFT_Entry_Attribute_Type * stpAttType;

    printf("========================= MFT Entry Attribute Analysis =========================\n");
    printf("Attribute Type                   : ");
    stpAttType = MFT_Attr_Type;
    while(1)
    {
        if(257 == (stpAttType->usNum))
        {
            break;
        }
        else if ((*((U32*)((U8*)p+0))) == stpAttType->usNum) /* 이동은 U8만큼으로 하고 보는건 U32로 보겠다 */
        {
            break;
        }
        ++stpAttType;
    }
    printf("%s\n", stpAttType->cDes);
    printf("Lenth of Attribute               : %dBytes\n", *((U32*)((U8*)p+4))); /* 이 길이를 알아내면 #2의 위치를 알 수 있다. */
    printf("Non-Resident Attribute           : %s\n", 1==(*((U8*)p+8)) ? "Yes":"No");
    printf("Lenth of Name                    : %d\n", *((U8*)p+9));
    printf("Offset to Name                   : %d\n", *((U16*)((U8*)p+10)));
    printf("Attribute Flags                  : ");
    if ( 0 != (0x0001 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Compressed ");
    }
    if ( 0 != (0x4000 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Encrypted ");
    }
    if ( 0 != (0x8000 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Sparse ");
    }
    if ( 0 == (0xC001 & (*((U16*)((U8*)p+12)))) )
    {
        printf("Nothing");
    }
    putchar('\n');
    printf("Attribute Identifier             : 0x%04X\n", *((U16*)((U8*)p+14)));

    if(0==(*((U8*)p+8)))	// Resident Attribute 
    {
        printf("=== Resident Attribute========================\n");
        printf("====== Size of Content           : %d\n", *((U32*)((U8*)p+16)));
        printf("====== Offset to Content         : %d\n", *((U16*)((U8*)p+20)));
        printf("====== Index Flag                : %s\n", 1==(*((U8*)p+22)) ? "Yes":"No");
        printf("====== Padding                   : 0x%02X\n", *((U8*)p+23)); /* Reserve ㅇ */
        printf("==============================================\n");
    }
    else					// Non-Resident Attribute 
    {
    }
	
    if(0!=(stpAttType->fp))     /* 호출 함수가 있다면 호출 한다. */
    {
        (stpAttType->fp)(    (U8*)p + (*((U8*)p+20))     ); /* 함수 포인터 */
    }
    return (U8*)p + (*((U32*)((U8*)p+4))) ;
}
  • 3번 줄에서 위에서 선언한 MFT_Entry_Attribute_Type * stpAttType 포인터 변수 선언
  • 7번에서 전역으로 선언된 MFT_Attr_Type을 stpAttType에 대입
  • 8번줄에서 무한 루프를 돌면서 해당하는 값이 있는지 찾고 없으면 다음 값으로
  • 20번줄에서 해당 메세지를 출력
  • 58번줄에서 함수포인터 사용여부를 검사하여 호출 또는 넘어간다.

위와 같은 기법을 이용하면 메뉴 호출또는 메세지등을 손쉽게 할 수 있다.


저작자 표시
신고

'컴퓨터 언어 > C' 카테고리의 다른 글

pThread를 이용한 Thread  (0) 2013.03.05
Static 변수  (0) 2013.02.25
메세지 기법  (0) 2013.01.16
배열의 이름은 첫번째 원소의 주소이다.  (0) 2012.12.20
문자열, 그것은 배열.  (2) 2012.06.11
Makefile을 작성하자.  (2) 2012.06.10
#include <stdio.h>

int main()
{
    float f[5];

    if(f == &f[0])
    {
        /* 항상 이곳이 실행된다 */
    }

    return 0;
}
f는 배열의 이름이며, &f[0]은 첫번째 원소의 주소다.

포인터를 이용한 배열 사용
#include <stdio.h>

int main()
{
    // 배열을 정의
    int nArray[10];
    int* p = &nArray[0];

    // 배열을 탐색하면서 값을 넣는다.
    for(int i = 0; i < 10; ++i)
    {
	*(p + i) = i;
    }

    return 0;
}

  • p + i 는 괄호에 쌓여있기 때문에 제일먼저 계산이 된다.
  • *(p + 1)이라고 해주면 i 번째 원소 자체를 의미하게 된다. 즉 nArray[i]와 똑같은 의미가 되는 것이다.
    • *(p + 3) == p[3]
    • *(p + 0) == p[0]
  • 포인터는 다른 원소를 가리키게 변경할 수 있지만, 배열의 이름은 항상 첫번째 원소의 주소만을 의미하는 상수라는 점이다. 즉, nArray++ 같은 것은 불가능하다.

배열을 가리키는 포인터

#include <stdio.h>

int main()
{
    long lArray[20];

    /* 포인터가 배열을 가리킴 */
    long (*p)[20] = &lArray;

    /* 포인터를 통해서 배열 사용 */
    (*p)[3] = 300;

    /* 결과 확인 */
    printf("%lArray[3] = %d\n", lArray[3]);
    
    return 0;
}
  • []연산자가 * 연산자보다 우선 순위가 높다.
  • long* p[20]이라고 써주면 p[20]이 먼저 해석, long* 타입의 원소 20개를 갖는 배열을 정의 한다.
  • 괄호를 사용해서 우선 순위를 바꿔줄 필요가 있다.
  • 그럼 *p가 먼저 해석이 되기 때문에 long타입의 원소 20개를 갖는 배열의 대한 포인터가 정의 된다.
저작자 표시
신고

'컴퓨터 언어 > C' 카테고리의 다른 글

Static 변수  (0) 2013.02.25
메세지 기법  (0) 2013.01.16
배열의 이름은 첫번째 원소의 주소이다.  (0) 2012.12.20
문자열, 그것은 배열.  (2) 2012.06.11
Makefile을 작성하자.  (2) 2012.06.10
다수의 소스 컴파일을 도와줄 Make  (2) 2012.06.10

문자열은 문자형의 배열을 말한다. 문자를 메모리상에 차례대로 둔 것과 같다. 문자열이 메모리 상에 어떻게 배치되는지는 차차 적도록 하고, 문자열에 대해서 좀 알아보면 다음과 같다.

문자열 처리는 프로그래밍에 있어서 많은 부분을 차지한다. 우리가 잘 알고있는 웹브라우져도 일종에 거대한 문자열 해석기와 같다. 웹브라우져는 전송받은 HTML 문서를 똘똘하게 분석하기 시작한다. 분석하는 과정중에는 앞서 쓴 적이 있는 토큰의 개념도 가지며 이제부터 써 내려갈 문자열 처리에 관한 기법들을 브라우져들만의 독자적인 알고리듬을 통해서 TAG 또는 스크립트들을 빨리 처리하기 위해 고군분투하는 것을 알 수 있다. 이외 또 하나의 문자열 분석기는 우리가 잘 아는 컴파일러라 할 수 있다. 컴파일러는 우리가 작성한 코드를 토큰 단위로 보며 이것을 문법이 맞는지 분석을 하고 어셈블리어로 뽑아내기 위해 CPU를 항상 독점 하다싶이 사용한다. 아래는 CPU가 컴파일러에게 능욕당하는 장면.

※컴퓨터 수명이 단축되는 기분이다. CPU의 온도가 약 60도를 웃돈다.

문자 상수와 문자열 상수 비교

  • 문자 상수
    • 'a', '3', '%', '+'
    • 문자 상수는 작은 따옴표로 문자 하나를 둘러 싼다.
    • 문자 상수는 1byte만을 차지한다.
  • 문자열 상수
    • "My name is Raven."
    • 문자열 상수는 따옴표로 다수의 문자 상수들을 둘러 싼 형태이다.
    • 문자열 상수는 강제적으로 컴파일러에 의해 문자열 마지막에 NULL 문자가 추가된다.
    • 추가된 NULL문자로 인하여 실제 적혀있는 문자들의 크기보다 1byte가 많다.

아래의 코드는 실제 적혀있는 문자열의 수와 메모리상에서 차지하고 있는 크기를 알아볼 수 있다.

// 문자열의 길이를 알아보자.

#include <stdio.h>
#include <string.h>

int main()
{
    int length;
    int size;

    length = strlen("My name is Raven");  /* strlen은 문자열에 일는 문자수를 반환한다. NULL문자 제외. */
    size = sizeof("My name is Raven");    /* sizeof 는 문자열이 가지고 있는 메모리 크기를 반환한다. NULL 문자 포함. */

    printf("Length of string : %d\n", length);
    printf("The size of string : %d\n", size);
    
    return 0;
}

<실행결과>

문자열 상수는 프로그램 내의 모든 변수가 심볼 테이블(Symbol Table)에 기록되어 쓰이는 것 처럼 모든 상수도 상수 테이블(Constant Table)에 주소와 함께 등록 된다. 문자열 상수 "My name is Raven"의 값은 상수 테이블 내에 "My name is Raven"이 저장되어 있는 주소를 값으로 가지고 있다.

문자열이 주소를 어떻게 가지는지 간단한 프로그램을 작성해서 알아볼 수 있다.


// 문자열이 저장된 메모리의 주소를 나타내는 프로그램.
#include <stdio.h>

int main()
{
    char *p;                    /* 주소를 저장 할 포인터 P 변수를 생성. */

    printf("%s %p\t\n", "abc", "abc"); /* 문자열은 문자열 그 자체가 주소값을 저장하고 있다는 것을 알 수 있다. */
    printf("%s %p\t\n", "abc", "abc"); /* 한번 선언된 문자열은 다시 선언한다고 해서 위치가 변하거나 다른 주소를 가지지ㅈ 않는다. */

    p = "abc";                  /* 포인터 p에 문자열 "abc"의 주소를 넣는다. */

    printf("%s %p\t\n", p, p);  /* p는 문자열 "abc"의 값을 출력한다. */
    
    return 0;
}

여기서 주목해야할 점은 "abc"가 가진 값이 무엇인가 하는 점이다. 저기서 출력한 것은 적혀있는 "abc" 그대로를 출력한 것인가 아니면 어떠한 메모리 영역에 자리잡고 있는 abc를 출력한 것인가? 위의 코드와 결과에서 봤듯이 문자열 상수 "abc"는 상수 테이블에서 자신에게 주어진 주소를 참고하여 메모리 영역(CODE 영역)에 저장되어있는 자신의 값을 출력한다.


신고

'컴퓨터 언어 > C' 카테고리의 다른 글

메세지 기법  (0) 2013.01.16
배열의 이름은 첫번째 원소의 주소이다.  (0) 2012.12.20
문자열, 그것은 배열.  (2) 2012.06.11
Makefile을 작성하자.  (2) 2012.06.10
다수의 소스 컴파일을 도와줄 Make  (2) 2012.06.10
ASCII Code는?  (1) 2012.06.09

Make와 Makefile은 실과 바늘의 관계, 또는 그 이상이다. Makefile이 없는 make는 초라하며 Make가 없는 Makefile은 바늘없는 실이다. Makefile을 잘 작성해 두면 두고 두고 편리하다.

가장 커다란 부분을 차지 하는 두가지 부터 살펴본다. 문법이라고도 볼 수 있는 부분이며 들여쓰기 등은 반드시 지켜져야 하는 부분이다. 이 부분은 사용했던 편집기에 따라서 본의 아니게 에러를 일으키는 부분이라 먼저 언급하고 넘어가도록 하자.

make 명령을 내렸는데 아래와 같은 에러떳고 아무리 makefile을 살펴봐도 이유를 알 수 없다면 아래 명령어를 이용해서 makefile을 한번 살펴보자.

Makefile을 od 명령어로 살펴 보기

  • 매크로(Macro)와 확장자(Suffix)
    • 매크로는 다음과 같은 사전적 의미를 가지고 있다.
      "컴퓨터에서, 하나의 명령으로 여러 가지 명령을 일괄적으로 수행하도록 하는 조작. 동일하게 반복되는 입력 작업에서 반복 작업의 횟수를 줄여서 작업을 효율적으로 하는 데 쓰인다." - 다음사전
    • makefile에서의 매크로는 마치 변수처럼 사용된다. 짧은 단어에 공통적으로 사용할 수 있는 명령어나 긴 명령어, 파일명을 나열 함으로 사용자 입장에서는 그것들을 한번만 적고 사용시에는 짧은 단어만 적음으로 불필요한 시간적 낭비를 막을 수 있으며 명령어를 통일 시킬 수 있다.
    • 매크로 선언은 아래와 같이 한다.
      CC = gcc    //  C Compiler라는 유닉스에서 쓰이는 compiler를 gcc로 받아들이게 한다.
      OBJECTS main.o strlen2.o     //  OBJECTS라는 매크로를 만들고 거기에 파일이름 두개를 명시해 둔다.


신고

'컴퓨터 언어 > C' 카테고리의 다른 글

배열의 이름은 첫번째 원소의 주소이다.  (0) 2012.12.20
문자열, 그것은 배열.  (2) 2012.06.11
Makefile을 작성하자.  (2) 2012.06.10
다수의 소스 컴파일을 도와줄 Make  (2) 2012.06.10
ASCII Code는?  (1) 2012.06.09
자료형  (1) 2012.06.09

Make는 그 뜻에서 알 수 있듯이 무언가를 만들다 라는 뜻을 가진 동사이다. 우리가 사용하게 될 make는 GNU에서 만든 Gnu Make를 사용을 한다.

make는 하나의 프로그램 소스들을 컴파일 하며 새로이 바뀐 부분을 알아서 확인하여 새로 컴파일을 하도록 하여 사용자가 일일이 소스들을 컴파일 할때 거치는 번거로운 과정을 거치지 않도록 도와주는 것에 목적이 있다.

GNU make는 보통 GNUmakefile, Makefile, makefile 중에서 하나가 있으면 그 파일을 읽게 된다. 하지만 일반적으로 Makefile을 추천하게 되는데, 그 이유는 우선 GNUmakefile은 기존의 make에서 인식을 못한다는 단점이 있고, makefile은 보통 소스 파일에 묻혀서 잘 안보이게 되기 때문이다. - KDLP 임대영님의 GNU Make 강좌.

Gnu Make는 소스를 컴파일할 디렉토리에 있는 makefile의 존재를 확인하는데 이때 순서가 대문자로 이루어진 이름부터 소문자로만 이루어진 순서로 찾게 된다.

  • Make가 makefile를 찾는 우선 순위 
    • GNUmakefile    //    다른 make 와 호환이 안되기 때문에 사용하지 않는다.
    • Makefile    //    눈에 잘 띄고 소문자보다 우선순위가 높으므로 이것을 애용하도록 하자.
    • makefile    //    Makefile 과 더불어 쉽게 볼 수 있는 makefile

프로그램을 개발하다 보면 Source file이 방대해지고 적절히 맞게 팀원들에게 배분할 필요가 있다. 그리고 이 Source 파일들은 서로 필요한 부분에서 의존하고 있는데 바뀐 함수를 이용하는 다른 파일도 새롭게 컴파일 되어야 한다. 이때 그 양이 많거나 헷갈리지 않게 하기 위해서라도 make는 필수적이다.

아래는 make와 make 파일을 어떻게 사용하는지 간단하게 적어두었다. 아래와 같은 makefile이 있다고 가정하고 main.c strcmp2.c strlen2.c 도 함께 있어야 한다.

CC = gcc    //    변수 처럼 선언해서 대입해서 쓰는 매크로.
OBJECTS = main.o strcmp2.o strlen2.o    //  모든 파일명을 다 적지 않기 위해서 하나의 매크로에 적어 둔다.

all: BEGIN $(OBJECTS)    //    형식은 레이블 명 : 의존성 걸린 파일명들.
	@$(CC) -o $(OBJECTS)    //    tab키로 반드시 들여쓰기를 해야한다.
	@echo Compilation is done.

BEGIN:
	@echo Compilation will start soon..

main.o: main.c
	@$(CC) -c main.c

strcmp2.o: strcmp2.c
	@$(CC) -c strcmp2.c

strlen2.o: strlen2.c
	@$(CC) -c strlen2.c
clean:
	@rm -rf $(OBJECTS)

사용은 make label 명 을 적어서 사용 할 수가 있다. 위의 makefile의 예를 들어서 사용해 보면,

 $ make all    //    makefile에 작성되어있는 all의 label을 실행하라 라는 명령어 일반적으로 컴파일을 시작하는 명령어 이며 make만 쳐도 make all을 찾는다.
$ make clean     //    makefile에 작성해 두었는 것 처럼 링크작업이 끝난 object 파일을 삭제한다. 


신고

'컴퓨터 언어 > C' 카테고리의 다른 글

문자열, 그것은 배열.  (2) 2012.06.11
Makefile을 작성하자.  (2) 2012.06.10
다수의 소스 컴파일을 도와줄 Make  (2) 2012.06.10
ASCII Code는?  (1) 2012.06.09
자료형  (1) 2012.06.09
어휘적 최소 단위 "토큰"  (1) 2012.06.08

컴퓨터의 메모리는 0과 1 즉 2진수로만 기록할 수 있게 되어있다.. 1 바이트 내에 저장된 데이터는 0과 1의 조합인 2진수로 표시할 수 있다. 2진수를 가지고 문자를 다루기 위해서는 각 문자에 해당되는 2진수의 값을 정해야 할 필요가 있다.

한 문자에 해당하는 2진수를 정한 코드에는 CDC SCIENTIFIC, ASCII(American Standard Code for Information Interchange), 그리고 EBCDIC(Extended Binary Coded Decimal Interchange Code) 3가지가 있다. 컴퓨터의 기종에 따라 사용하는 문자코드는 다르다. IBM 컴퓨터의 경우 대부분의 기종은 EBCDIC 코드를 사용하지만 IBM PC에서는 ASCII 코드를 사용한다.

일반적으로는 PC에서는 ASCII 코드가 사용되고 있다. 원래 ASCII 코드는 1 바이트내의 7 비트만을 이용해서 10진수 0에서 127까지의 128 개의 문자로 구성되었다. 여기에는 영어 알파벳의 대문자와 소문자, 그리고 보조문자들과 제어문자들을 포함하고 있었다. 후에 IBM에서 마지막 한 비트를 포함하여128부터 256까지 확장시켜 256개 문자로 만들었다. 여기에는 비영어 문자와 그래픽 문자를 포함시켰다. 그리고 컴퓨터에서 잘 사용되지 않았던 0부터 31까지를 그래픽 문자들 로 재정의했다. 이것을 IBM확장 ASCII 코드(IBM Extended ASCII Code)라고 부른다.

ASCII 코드란 문자 ‘A’를 65, ‘B’를 66 등으로 정한 것으로, 각 문자의  ASCII 코드는 printf() 함수를 이용하여 출력할 수 있다. 아스키 코드이후 다른 언어를 사용하는 세계 각국의 문자를 반영하기 위해서 한문자를 2 바이트에 넣어 65,535 개의 문자를 표현할 수 있는 unicode가 제시되어, 앞으로의 문자 체계로 사용될 예정이다. 유니코드는 웹 사이트 "http://unicode.org"에서 검색할 수 있다.

아래의 아스키 코드는 linux에서 제공하는 ASCII Man page에서 쉽게 볼 수가 있다.

$ man ascii




신고

'컴퓨터 언어 > C' 카테고리의 다른 글

Makefile을 작성하자.  (2) 2012.06.10
다수의 소스 컴파일을 도와줄 Make  (2) 2012.06.10
ASCII Code는?  (1) 2012.06.09
자료형  (1) 2012.06.09
어휘적 최소 단위 "토큰"  (1) 2012.06.08
메모리의 구성  (1) 2012.06.08

자료형

컴퓨터 언어/C 2012.06.09 13:01
자료형 또는 데이터 타입이란, 정수형 또는 실수형 같이 '공통된 속성을 가진 데이터의 모임'을 말한다. 프로그래밍 언어가 여러가지 데이터 자료형을 가지는 이유는 다양한 문제를 효율적으로 풀기 위함이다.

경우에 따라서 우리는 다양한 형태의 수를 이용하기 때문에 2진수로만 동작하는 컴퓨터의 입장에서 이것을 미리 명시함으로서 필요한 형태로 데이터를 해석하는 것에 목적을 둔다. 또한 데이터의 저장형식에 따라 메모리를 절약하기 위해서 각 타입별로 할당하는 메모리의 크기가 다르다.

C언어의 기본 자료형은 아래와 같다

  • Char (Character)
    • 문자형
      • 1byte의 공간을 할당 받음. 따라서 1 byte는 8 bit 이기에 character형은  2^8(2의 8승)의 수를 가지게 된다.
      • unsigned character 1byte 는 0 에서 255의 수를 가진다.
      • signed character 는 1byte -128에서 127까지의 수를 가진다.
    • 문자 상수는 ' ' 작은 따옴표 안에 넣어서 나타낸다.
      • 'a', '5', '%'
      • 여기서 정수 5의 문자 5는 완전히 다른것으로 문자 5는 ASCII 코드의 53을 의미한다.
  • Int (Integer)
    • 정수형
      • 정수형의 표준은 int 형입니다.
      • 수학에서의 정수는 무제한에서 무제한 까지이지만 컴퓨터에서의 정수는 물리적인 제한이 있기 때문에 16비트나 32비트 그리고 64비트에서 가지는 int형 의 메모리 크기는 각기 다를 수 있지만 일반적으로 4바이트를 기준으로 합니다.
      • 4바이트일 경우 unsigned int 는 2의 32승인 0 ~ 4,294,967,295 만큼의 수를 다룰 수 있으며 singed int는 -2,147,483,648 ~ 2,147,483,647 만큼의 수를 허용합니다.
  • Float (Floating point number)
    • 실수형
      • 실수를 나타내는 자료형은 아래와 같이 세가지 형태가 있다.
        • float 형 4 byte.
        • double 형 8 byte.
        • long double 형 10 byte.
      • 4 byte를 가지며 범위는 3.4 x 10-^38 승 부터 3.4 x 10^38승 까지.
      • 실수형 데이터는 메모리내에서 부호부분과 가수부 및 지수부 세부분으로 나누어 저장한다. 32 bit 중 8 bit는 지수부와 부호를 나타내고 나머지 24비트는 가수부이다.
  • Double (Double precision floating point)
    • 배정도 실수형
  • Void
    • 자료형 없음.

기본 자료형 가운데 void 형을 제외한 네가지 자료형은 형수정자(type modifier)를 이용하여 파생자료형을 만들 수 있다.

  • signed
  • unsigned
  • long
  • short


신고

'컴퓨터 언어 > C' 카테고리의 다른 글

다수의 소스 컴파일을 도와줄 Make  (2) 2012.06.10
ASCII Code는?  (1) 2012.06.09
자료형  (1) 2012.06.09
어휘적 최소 단위 "토큰"  (1) 2012.06.08
메모리의 구성  (1) 2012.06.08
C의 함수 구조  (1) 2012.06.07

프로그램 내의 “어휘적최소단위”를 토큰 이라 부른다.

  • 키워드(keyword)

    키워드는 예약어라고도 하며 C언어에서 먼저 사용하겠다고 명시해 둔 것들이라 사용자가 지정된 목적외에 다른 목적으로 사용할 수 없다.

    • 키워드 목록 보기

  • 사용자 정의 식별자(user-defined identifier)

    사용자 정의 식별자는 변수(varialbe)나 함수(function)들의 이름으로 만들어 사용하는 “토큰”이다. 식별자는 아래와 같이 만들 수 있다.

    • 첫 글자는 영어 알파벳이나 밑줄이 올 수 '있다.'
    • 그 뒤에는 영어, 숫자, 밑줄이 올 수 있다.
    • 하나의 식별자는 보통 32개의 문자를 허용한다.
    • 연산자(operator)
    • 상수(constant)
    • 보조문자(punctuation symbol)

    소문자와 대문자가 철저히 다르게 취급되므로 주의해서 사용해야 한다.

int i_num;    // 소문자로 선언되 이 변수와,
int i_Num;  //첫 글자가 대문자로 쓰여진 i_Num은 서로 다른 변수이다.

식별자를 만들때는 그 이름을 되도록이면 명확하게 만들어 주는 것이 좋은 프로그래밍 습관이다. 의미는 쉽게 파악할 수 있어야 하며 함수는 그 기능을 알 수 있게 명료하게 작성하자. 이것은 소스의 이해도를 크게 높힐 수 있다.

//  올바른 식별자 사용의 예
inum
i_num
i_num_2
number

//  잘못된 식별자 사용의 예
4number  //  숫자가 처음 글자로 올 수 없다.
i-number  //  밑줄 '_' (under-bar)가 아닌 '-'는 사용할 수 없다. 이것은 컴파일러를 연산자로 오해하게 한다.
name 2  //  띄워쓰기를 할 경우 하나의 식별자가 아니라 두개의 식별자로 구분한다.
name&  //  식별자에 특수문자를 이용할 수 없다
  • 연산자(operator)
    연산자 는 산술연산이나 논리연산 등 여러가지 연산을 위해 사용된다.
  • 보조문자(punctuation symbol)
    보조문자는 괄호()등 그 자체로는 의미를 가지고 있지는 않다. 하지만 키워드, 식별자 등과 함께 사용하여 구문형성을 명확히 해주는 역활을 한다. 세미콜론 ; 은 그 자체는 의미를 가지지 않지만 각명령의 끝을 나타낸다.
  • 상수(constant)
    프로그램 내에서 데이터 값을 나타내는 것은 변수와 상수이다. 변수는 특정 메모리 공간의 이름으로 그 값이 필요에 따라 바뀌지만, 상수는 미리 정해져서 바뀌지 않는 값을 말한다. 상수에는 다음과 같이 있다.
    • 정수 상수
      • 3, 2, 1
    • 실수 상수
      • 3.89 12.7
    • 문자 상수
      • 'A', '$'
    • 문자열 상수
      • 'My name is Raven'


신고

'컴퓨터 언어 > C' 카테고리의 다른 글

ASCII Code는?  (1) 2012.06.09
자료형  (1) 2012.06.09
어휘적 최소 단위 "토큰"  (1) 2012.06.08
메모리의 구성  (1) 2012.06.08
C의 함수 구조  (1) 2012.06.07
부호 비트 방식  (0) 2012.04.03