운영체제에서 주어진 일을 하는 최소단위는 프로세스라는 것을 알고 있을 것이다. 프로세스는 프로그램의 실행된 이미지로 운영체제의 메인메모리에 위치한다.

이렇게 프로그램이 실행되어서, 프로세스가 생성되면 프로세스는 컴퓨터의 여러가지 기본자원을 사용할 수 있게 된다. 이 기본자원에 3개의 파일이 포함되어 있다. 바로 입력출력, 에러를 담당하는 3개의 파일들이다. 이것들을 표준입력, 표준출력, 표준에러라고 한다.

  • 표준입력 : 키보드로 부터 입력을 받기 위해서 사용한다.
  • 표준출력 : 모니터로 출력하기 위해서 사용된다.
  • 표준에러 : 에러도 역시 모니터를 통해서 출력된다는 점에서는 표준출력과 마찬가지다. 그러나 어떠한 구분도 없다면, 화면에 출력된 값이 정상적으로 처리된 메시지인지, 에러메시지 인지 확인할 수 없을 것이다. 때문에 표준에러라는 것을 따로 둬서 구분할 수 있게끔하고 있다.

이들 표준입/출력/에러 역시 파일의 형태로 다루어지며, 운영체제는 이를 위해서 예약된 숫자를 파일지시자로 할당한다. 표준입력은 0, 표준출력은 1, 표준에러는 2로 예약되어 있다.

간단한 예를 들어서 설명해보도록 하겠다.
#include <unistd.h> 
#include <string.h>

int main(int argc, char **argv)
{
char data[80];
char *msg = "Input Msg : ";
memset(data, 0x00, 80);

write(1, msg, strlen(msg)); // 1

read(0, data, 80); // 2
write(1, data, strlen(data)); // 3
write(2, "Error\n", 6); // 4
}
  1. "Input Msg"메시지를 모니터에 표준출력 한다.
  2. 표준입력을 통해서 데이터를 읽어들인다. 읽어들인 데이터는 data 에 복사한다.
  3. data에 복사된 내용을 data의 길이 만큼 모니터에 표준출력 한다.
  4. Error라는 메시지를 모니터에 표준에러형태로 출력한다.
이 프로그램을 실행시키면 다음과 같은 결과를 확인할 수 있을 것이다.
# ./write 
Input Msg : hello world
hello world
Error
  • write(2)
    이 함수는 파일지시자(첫번째 인자)가 가리키는 파일에 "쓰기" 위해서 사용한다.
  • read(2)
    이 함수는 파일지시자가 가리키는 파일에서 데이터를 "읽기" 위해서 사용한다.

표준입력과 표준출력을 이해하는데에는 별 어려움이 없을 것이다. 그럼 표준에러와 표준출력을 어떻게 구분할 수 있느냐 하는 문제가 남는다.

표준에러는 쉘의 재지향을 이용해서 따로 분리해서 읽을 수 있다. 재지향은 >을 쓰면 된다. - 2장 리눅스와 C언어참고 - 또한 2>와 같이 표준에러만을 분리해서 재지향 시킬 수가 있다. 여기에서 2가 바로 표준출력을 가리키는 파일지시자 번호다. 이제 다음과 같이 표준에러만 별도의 파일에 재지향 시켜보도록 하자.
# ./write 2> dump.log 
Input Msg : hello world
hello world
# cat dump.log
Error
표준에러가 모니터 화면이 아닌, dump.log 파일에 저장된걸 확인할 수 있을 것이다. 이로써, 표준에러와 표준출력이 모니터를 출력방향으로 하고 있지만, 명백히 구분되는 것임을 이해했을 것이다.

출처 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/C/Documents/CprogramingForLinuxEnv/Ch13_Input_Output

'It's IT > It's System(linux,win)' 카테고리의 다른 글

Linux 공부를 함 해볼까??????  (0) 2019.12.24
linux, unix shell script 조건문에서 사용하는 기호  (0) 2008.01.17
퍼미션, CHMODE  (0) 2007.12.14
VI명령어  (0) 2007.12.14
PING  (0) 2007.12.14
출처 : http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/C/Documents/CprogramingForLinuxEnv/Ch11_Structure

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

struct userinfo
{
char name[20];
int age;
};

int main(int argc, char **argv)
{
int age;
int i;
char buf[40];
struct userinfo myfriend[5];

for (i = 0; i < 5; i++)
{
printf("Name : ");
fgets(buf, 19, stdin);
buf[strlen(buf)-1] = '\0'; // <--- 1
sprintf(myfriend[i].name, "%s", buf);

printf("Age : ");
fgets(buf, 19, stdin);
age = atoi(buf);
myfriend[i].age = age;
}

printf("=======================\n");
for (i = 0; i < 5; i++)
{
printf("%12s : %d\n", myfriend[i].name, myfriend[i].age);
}
}
fgets(3)은 키보드로 부터 문자열을 입력받기 위해서 사용하는 함수다. 1은 키보드로 입력된 개행문자를 제거하기 위해서 사용했다.

'It's my study ^^ 과연' 카테고리의 다른 글

open  (0) 2007.12.15
Library 만드는 법  (0) 2007.12.14
이중 포인터  (0) 2007.12.13
대입연산자  (0) 2007.12.12
Primitive Data Types  (0) 2007.12.10
출처:http://www.joinc.co.kr/modules/moniwiki/wiki.php/Site/C/Documents/CprogramingForLinuxEnv/Ch10_Pointer#s-10
포인터는 데이터가 저장된 주소를 가리키는 데이터 타입이다. 이는 어떠한 종류의 데이터타입이라도 가리키는 포인터의 생성이 가능함을 얘기한다. int 형 포인터, float 형 포인터가 좋은 예가 되겠다. 2차원 포인터는 포인터 데이터 타입을 를 가리키는 포인터이다. 이러한 특징 때문에 포인터의 포인터라고 부르기도 한다. 2차원 포인터의 가장 단적인 얘는 라인단위 편집기를 예로 들 수 있을 것이다. 아래와 같은 문장이 있다고 가정해 보자.

Hello World!!
My name is yundream.
What's your name.
Thank you.
 


이 문장을 각각의 라인단위로 저장을 하는 프로그램을 만든다고 가정해 보자. 그렇다면 4개의 char 형 포인터가 필요할 것이다. 이제 이 4개의 char 형 포인터 데이터를 저장하기 위한 포인터변수를 만들면 될것이다. 포인터를 저장하는 포인터변수인 셈이다. 포인터의 포인터변수는 별표를 하나 더 붙이는 것으로 간단히 선언할 수 있다. 위 예의 경우 char 포인터를 저장하기 위한 포인터는 아래와 같이 선언할 수 있다.

char **data;
 

차원이 늘어날 수록 그만큼의 별표를 붙여주면 된다. 사용할일이 거의 없겠지만, 3차원 포인터는 다음과 같다.

char ***data;
 


그럼 2차원 포인터를 이용해서 위의 문장을 출력하는 줄단위 출력 프로그램을 만들어 보자. 포인터형 변수의 이름은 char **data로 선언한다. 선언을 했다면, 메모리 할당을 해야 할것이다. 2차원 포인터 이므로 2번의 메모리 할당이 이루어져야 한다.

   1. 4개의 문자형 포인터를 저장하기 위한 공간 할당.
   2. 각 문자데이터를 저장하기 위한 공간할당.

우선 문자형 포인터를 저장하기 위한 공간은 다음과 같이 할당할 수 있다.

char **data;
data = malloc(sizeof(char *)*4);
 

데이터를 저장하기 위한 공간을 할당하려면, 데이터 타입의 크기를 알고 있어야 한다. 앞서 sizeof를 이용하면 데이터 타입의 크기를 얻어올 수 있음을 언급했다. 우리가 저장하기 위한 데이터 타입은 문자형 포인터이므로 sizof(char *)를 이용해서 크기를 얻어올수 있다. 이게 4개가 필요하므로 *4를 해주면 4개의 문자형 포인터 데이터를 저장하기 위한 공간을 할당받게 된다. 포인터 데이터 타입의 크기는 4 이므로 16byte 만큼의 공간을 할당받게 된다.

이제 4개의 문자형 포인터가 사용할 공간을 할당하고, 그 주소값(포인터)를 얻어와야 할 차례다. 원칙적으로 하자면, 각 문자열의 크기만큼 다르게 할당해야 겠으나, 그렇게 하면 귀찮으니, 모든 문자열을 넣기에 충분하다고 생각되는 25byte 를 동일하게 할당해보도록 하겠다. for 루프문을 이용하면 간단하게 할당할 수 있다.

char **data
data = malloc(sizeof(char *)*4);
for (i = 0; i < 4; i++)
{
    *data = malloc(sizeof(char) * 25);
    *data++;
}
 

'It's my study ^^ 과연' 카테고리의 다른 글

Library 만드는 법  (0) 2007.12.14
구조체(Struct)  (0) 2007.12.13
대입연산자  (0) 2007.12.12
Primitive Data Types  (0) 2007.12.10
C/C++ Language  (0) 2007.12.06
대입연산자는 같은 타입에 대해서만 허용되는 연산자이기 때문에, 배열에 문자열을 대입하는건 C 문법에 어긋나기 때문이다. 결국 문자열을 처리하기 위해서는 별도의 함수를 만들어서 사용하는 수 밖에 없다. 다행히 C 는 표준 라이브러리 형식으로 몇개의 유용한 문자열 처리 함수를 제공한다. strcat(3), strcpy(3)와 같은 함수가 문자열 처리를 위한 대표적인 함수다. 다음은 strcpy 함수를 이용해서 문자열을 복사한 프로그램이다.
#include <stdio.h> 

int main()
{
char hello[12];
strcpy(hello,"hello world\0");
printf("%s\n", hello);
}

'It's my study ^^ 과연' 카테고리의 다른 글

구조체(Struct)  (0) 2007.12.13
이중 포인터  (0) 2007.12.13
Primitive Data Types  (0) 2007.12.10
C/C++ Language  (0) 2007.12.06
Comback of Se Ri Pak  (0) 2007.08.17

Primitive Data Types

인간은 매우 다양한 형태의 데이터를 다루기를 원하고, 그런일을 할 수 있는 프로그램을 만들어 낼 수 있어야 한다. 다루는 데이터의 형태가 다양하니, 데이터 타입 역시 다양하면 좋을 것이다. 그러나 컴퓨터는 매우 단순한 기계다. 쓸데없이 데이터 타입을 이것 저것 만들면, 이것을 다루는 컴퓨터 역시 달가워하지 않을 것이다. 프로그래머 역시 각 데이터 타입에 따른 고려사항이 늘어나니 권장할만한 사항이 아니다.

그래서 데이터타입을 다루어야 하는 프로그래밍 언어는 Primitive Data Type이라고 불리우는 최소한의 반드시 필요한 데이터 타입을 지원하고 있다. Primitive Data Type은 원시 데이터 타입 이라고 부르기도 한다.

각 원시 데이터 타입은 고유의 크기를 가지고 있으며, 표현할 수 있는 데이터의 한계가 정의되어 있다. 다음은 C 언어에서 지원하는 원시 데이터 타입과 크기, 데이터 범위를 보여주는 표다.

숫자형 원시 데이터 타입

숫자를 표현하기 위해서 사용되는 데이터 타입이다. 크게 정수형 데이터를 표현하기 위한 정수형 원시 데이터 타입부동소숫점형 원시 데이터 타입으로 나눌 수 있다.
  • 정수형 원시 데이터 타입
    char 1byte -128 127
    short 2byte -32768 32767
    long int 4byte 2,147,483,648 2,147,483,647
    long long int 8byte 9,223,372,036,854,775,808 9,223,372,036,854,775,807

이들 정수형 데이터 타입들은 signed비트라는 것을 가지고 있어서, 음수까지 표현할것인지를 정의할 수 있다. 음수까지 표현할 거라면 signed를 양수만 표현할거라면 unsigned를 타입의 앞에 붙여준다. 따로 붙여주지 않았다면 signed 가 붙은걸로 해석을 한다. 즉 위의 데이터 타입은 실제로는 signed char, signed short, signed long int, signed long long int와 동일하다.

unsigned를 명시하게 되면 양의 정수만 표현하게 된다. 음의 정수를 표현할 필요가 없으니 그만큼 양수 쪽으로 표현범위가 늘어날 것이다. unsigned char 이라면 255, unsigned long int 라면 4,294,967,295 가 된다.

  • 부동소숫점형 원시 데이터 타입
    float 4byte +/- 10E-37 +/- 10E38
    double 8byte +/- 10E-307 +/- 10E308

'It's my study ^^ 과연' 카테고리의 다른 글

이중 포인터  (0) 2007.12.13
대입연산자  (0) 2007.12.12
C/C++ Language  (0) 2007.12.06
Comback of Se Ri Pak  (0) 2007.08.17
feasibility  (0) 2007.08.14

+ Recent posts