728x90

프로그램이 성공적으로 파일을 열면, fopen()은 파일 포인터(file pointer)를 리턴한다. 다른 입출력 함수들은 그 파일 포인터를 그 파일을 나타내는데 사용한다. 파일 포인터(FILE *fp)는 FILE을 가리키는 포인터 이다.

 

FILE은 stdio.h에 정의 되어있는 유도 데이터형이다. 포인터 fp는 실제 파일을 가리키지 않는다. 대신에 그 파일의 입출력에 사용되는 버퍼정보를 포함하여, 그 파일에 관한 정보가 들어있는 데이터 객체를 가리킨다.

 

표준 라이브러리에 있는 입출력 함수들은 버퍼를 사용하기 때문에, 버퍼가 어디에 있는지 알 필요가 있다. 또한 버퍼가 얼마나 채워져 있는지, 어느 파일을 사용하는지도 알 필요가 있다. 이 정보들은, 필요할때 함수들이 버퍼를 다시 채우거나 비우는 것을 가능하게 한다. fp가 가리키는 데이터 객체가 그 모든 정보를 가지고 있다.

 

fopen()함수는 그 파일을 열 수 없을때 (stdio.h에 정의되어있는) 널 포인터를 리턴한다. 몇가지 예를 든다면, fopen()함수는 디스크가 가득 차 있을 때, 파일이 찾는 디렉토리에 없을 때, 이름이 잘못 되었을 때, 접근이 제한되어 있을 때, 하드웨어에 문제가 있을 때 실패할 수 있다.

 

getc(), putc()함수는 getchar(), putchar() 함수와 아주 비슷하게 작동한다. 차이는, getc()와 putc()는 어느파일을 사용할 것인지 알려주어야 한다는 것이다.

ch=getc(fp) -> "fp가 나타내는 파일로부터 하나의 문자를 얻는다."

putc(ch,fpout) -> "문자 ch를 FIE포인터 fpout이 나타내는 파일에 출력한다."

putc()전달인자 리스트에서, 문자가 앞에오고 파일 포인터가 뒤에온다.

 

stdout은 stdio.h에 표준출력에 연결되는 파일 포인터로 정의되어 있다. 그러므로 putc(ch,stdout)은 putchar(ch)와 동일한 효과를 낸다. 실제로 putchar()는 일반적으로 putc()로 정의되어 있다.

 

파일로 부터 데이터를 읽는 프로그램은, 파일의 끝에 도달했을 때 읽기를 멈출 필요가 있다. getc()함수는, 하나의 문자를 읽으려 시도하다가 파일의 끝에 도달했다는 것을 발견하면, EOF라는 특별한 값을 리턴한다. 그래서 C프로그램은 파일의 끝을 읽은 후에 파일의 끝에 도달했다는 것을 알게 된다.

 

비어있는 파일을 읽으려 시도하는 문제를 피하려면, 진입조건 루프를 파일 입력에 사용해야 한다. getc()(그리고 다른 C의 입력 함수들)의 그와 같은 설계 특성때문에, 프로그램은 루프 몸체에 들어가기전 최초의 읽기를 시도해야한다.

ex)

int ch;

FILE *fp;

fp = fopen("abc.txt","r");

while((ch = getc(fp))!=EOF)                           //루프 들어가기전 진입조건

{

         putchar(ch);                                     //입력 처리

}

 

 

fclose(fp)함수는, 필요할 때 버퍼를 비우면서 fp가 가리키는 파일을 닫는다. fclose()함수는 파일을 성공적으로 닫았으면 0을 리턴하고, 그렇지 않으면 EOF를 리턴한다. fclose 함수는, 디스크가 가득 차있을 때, 플로피 디스크가 제거 되었을 때, 또다른 에러가 발생했을 때 파일을 닫는데 실패할 수 있다.

 

표준 파일을 가리키는 포인터

stdio.h 파일은, 세개의 파일 포인터를 C프로그램이 자동으로 여는 세개의 표준 파일에 연결한다.

        표준파일                              파일포인터                                 일반적으로

 -------------------------------------------------------------------------------------------------------------------------

        표준 입력                               stdin                                        키보드                                                      표준 출력                               stdout                                      스크린                                                      표준 에러                               stderr                                       스크린

위 포인터들은 모두 FILE을 가리키는 포인터형이다. 그래서 이들을 표준 입출력 함수들의 전달인자로 사용할 수 있다.

 

파일 입출력 함수들에게 어느 파일을 가지고 작업할 것인지 알려주기 위해 파일 포인터를 사용할 필요가 있다. getc()와 putc()와 마찬가지로 파일 입출력 함수들은 stdout과 같은, FILE을 가리키는 포인터를 지정할 것을 요구하거나, fopen()의 리턴값을 사용할 것을 요구한다.

 

동시에 열어 놓을수 있는 파일들의 개수에는 제한이 있다. 그 제한은 사용하는 시스템과 컴파일러에 따라 다르다. 일반적으로 그 제한은 10 ~ 20 개 이다. 또한, 파일들을 동시에 열어 놓지 않는다면, 서로 다른 파일에 같은 파일 포인터를 사용할 수 있다.

 

rewind()함수는 파일 포인터를 파일의 시작으로 옮긴다. rewind()는 파일 포인터를 전달인자로 사용한다.

 

fprintf()와 fscanf()함수는 FILE 포인터를 마지막 전달인자가 아니라 첫번째 전달인자로 사용한다.

 

fgets()함수는 세개의 전달인자를 사용한다. 첫번째 전달인자는, gets()와 마찬가지로, 입력을 저장할 주소(type char *)이다. 두번째 전달인자는, 입력 문자열의 최대 크기를 나타내는 정수이다. 마지막 세번째 전달인자는, 읽을 파일을 가리키는 파일 포인터다.

fgets(buf,STLEN,fp);

 

fgets()함수는 최대 문자열 크기보다 적은 수의 문자들을 읽을 때까지 또는 파일끝을 만날때까지 문자들을 읽되, 첫 개행 문자까지 읽는다. 그리고 fgets()는 읽은 것이 문자열이 되도록 종결 널문자를 추가한다. fgets()함수는 EOF를 만나면 NULL값을 반환한다. 이 값을 사용하여 파일의 끝에 도달했는지 검사할 수 있다.

 

fputs()함수는 두개의 전달인자를 사용한다. 첫번째 전달인자는 문자열의 주소다. 두번째 전달인자는 파일 포인터이다. 이함수는 그 주소에 들어있는 문자열을 파일포인터가 가리키는 파일에 기록한다.

fputs(buf,fp);

 

fgets()는 개행 문자를 유지하고, fputs()는 개행 문자를 덧붙이지 않기 때문에, 이들은 서로 협력하여 잘 동작한다.

 

fseek() 함수는, 파일을 마치 배열처럼 다룰 수 있게 한다. 이 함수는 fopen()에 의해 열려진 파일에 들어있는 특정 바이트로 직접 이동할 수 있게 해준다.

 

fseek()는 세개의 전달인자를 사용한다. 첫번째 전달인자는, 처리할 파일을 가리키는 FILE 포인터이다. 이 파일은 fopen()함수에 의해 미리 열려 있어야 한다. fseek()의 두번째 전달인자는 오프셋(offset)이라고 한다. 이 전달인자는 시작 위치로 부터 얼마나 멀리 가야하는지 알려준다. 이 전달인자는 long형 값이어야 한다. 이 값은 양수(앞으로), 음수(뒤로), 0(현재 위치에 머무른다)이 될 수 있다.

세번째 전달인자는 모드(mode)이다. 그것은 시작 위치를 나타낸다. ANSI에서, 모드와 관련된 명단 상수(manifast contant)들은 stdio.h헤더 파일에 정의되어 있다.

           모드                                시작위치

      SEEK_SET                              파일의 시작

      SEEK_CUR                             현재 시작

      SEEK_END                             파일의 끝

 

다음은 fseek() 함수 호출의 몇가지 예이다.

fseek(fp,0L,SEEK_SET);                   //파일의 시작으로 간다.

fseek(fp,10L,SEEK_SET);                  //파일의 시작에서 10바이트 앞으로 간다.

fseek(fp,2L,SEEK_CUR);                 //현재 위치에서 2바이트 앞으로 간다.

fseek(fp,0L,SEEK_END);                //파일의 끝으로 간다.

fseek(fp,-10L,SEEK_END);             //파일의 끝에서 10바이트 뒤로간다.

 

모든것이 성공적이면 fseek()은 0을 리턴한다. 파일의 경계를 벗어나려는 시도와 같은 에러가 있으면 fseek()은 -1을 리턴한다.

 

ftell()함수는 long형이다. 이 함수는 현재의 파일 위치를 리턴한다. ANSI C에서, 이 함수는 stdio.h에 선언되어 있다. ftell()은 파일의 시작으로 부터 첫바이트를 0으로 하는 바이트 수를 리턴함으로써 적용된다. 그러나 텍스트 모드로 열린 파일들에 반드시 적용되는 것은 아니다.

 

텍스트 모드에서 제대로 동작하는 fseek() 호출

       함수 호출                                        효과

fseek(file,0L,SEEK_SET)                        파일의 시작으로 간다.

fseek(file,0L,SEEK_CUR)                       현재 위치에 머무른다.

fssek(file,0L,SEEK_END)                       파일의 끝으로 간다.

fseek(file,ftell-pos,SEEK_SET)               파일의 시작에서 ftell-pos 만큼 떨어진 위치로 간다. ftell-pos는 ftell()이                                                               리턴하는 값이다.

 

fseek()와 ftell()함수들은 파일 크기를 long형으로 나타낼 수 있는 값으로 제한한다. ANSI C는 커다란 파일을 처리하도록 설계된 두개의 새로운 위치 지정 함수를 도입했다. long형 값으로 위치를 지정하는 대신에, 그 목적을 위해 설계된(파일 위치 데이터형을 의미하는) fpos_t라는 새로운 데이터형을 사용한다.

 

ANSI C는 fpos_t를 사용하는 방법을 정의한다. fgetpos()함수는 다음과 같은 프로토 타입을 가진다.

int fgetpos(FILE * restrict stream, fpos_t * restrict pos);

호출되었을 때, 이 함수는 fpos_t값을 pos가 가리키는 위치에 넣는다. 그 값은 파일 안에서의 어떤 위치를 나타낸다. 이 함수는 성공하면 0을 리턴하고, 실패하면 0이아닌 값을 리턴한다.

 

일반적으로, 표준 입출력을 사용하는 첫 단계는 fopen()을 사용하여 파일을 여는 것이다.(그러나 stdin, stdout, stderr 파일들은 자동으로 열린다는 것을 기억하라.) fopen()함수는 파일을 열 뿐만 아니라 버퍼(읽기- 쓰기 모드를 위한 두개의 버퍼)도 설정한다. 또한 이 함수는 파일과 버퍼에 관한 데이터가 들어있는 데이터 구조체를 설정한다. 그리고 다른 함수들이 그 구조체를 어디에서 찾아야 하는지 알 수 있도록 그 구조체를 가리키는 포인터를 리턴한다. 이 값이 fp라는 이름의 포인터변수에 대입된다고 가정하자. 우리는 이것을 fopen() 함수가 "하나의 스트림을 열었다"라고 말한다. 파일을 텍스트모드로 열면, 텍스트 스트림을 얻는다. 파일을 바이너리 모드로 열면 바이너리 스트림을 얻는다.

 

일반적으로 그 데이터 구조체는 스트림의 현재 위치를 나타내는 파일 위치 표시자를 가지고 있다. 또한 그 구조체는 에러와 파일끝을 나타내는 지시자, 버퍼의 시작을 가리키는 포인터, 파일 식별자, 버퍼 안으로 실제로 복사된 바이트 수에 해당하는 카운트도 가지고 있다.

728x90

'Programming > C' 카테고리의 다른 글

C언어 공부 29  (0) 2019.06.16
C언어 공부 28  (0) 2019.06.12
C언어 공부 26  (0) 2019.06.11
C언어 공부 25  (0) 2019.06.11
프로그래밍 연습 10  (0) 2019.06.08
728x90

파일 입출력

 

파일에 대한 두가지 입출력 수준(즉, 파일에 대한 접근을 처리하는 두가지 수준)중 어느 하나를 선택할 수 있다. 저수준 입출력(Low-level I/O)은 운영체제가 제공하는 기본적인 입출력 서비스를 사용한다. 표준 고수준 입출력(standard high - level I/O)은 C라이브러리 함수들의 표준 패키지와 stdio.h 헤더 파일정의들을 사용한다.

 

모든 운영체제가 동일한 저수준 입출력 모델로 표현될 수 있다는 보장이 없기 때문에, C 표준은 입출력 패키지만을 제공한다.

 

C프로그램은 사용자를 위해 표준 입력(standard input), 표준 출력(standard output), 표준 에러 출력(standard error output) 이라는 세개의 파일을 자동으로 연다. 표준 입력은 디폴트로, 일반적으로 시스템이 사용하는 키보드와 같은 입력 장치다. 표준 출력과 표준에러 출력은 둘다 디폴트로, 일반적으로 시스템이 사용하는 디스플레이 스크린과 같은 출력 장치이다.

 

표준 입력은 당연히 프로그램에 입력을 제공한다. 그것은 getchar(), gets(), scanf()가 데이터를 읽는 파일이다. 표준 출력은 프로그램의 정상적인 출력이 나타나는 곳이다. putchar(), puts(), printf()가 그 파일을 사용한다. 리다이렉션은 다른 파일들을 표준입력이나 표준 출력으로 인식되게 만든다.

 

표준 에러출력 파일의 목적은 에러 메시지들을 출력할, 논리적으로 구분되는 어떤 장소를 제공하는 것이다. 예를 들어, 출력을 스크린 대신에 파일로 보내는 리디렉션을 사용할 때, 표준 에러 출력으로 보내지는 에러 메시지들은 여전히 스크린에 표시된다. 에러 메시지들 마저도 파일로 보내진다면, 그 파일을 열어보기 전까지는 에러 메시지들의 존재를 알 수 없기 때문이다.

 

표준 입출력 패키지가 저수준 입출력에 비해 가지는 장점.

1. 다양한 입출력 문제들을 간단하게 처리하는 전문화된 많은 함수들을 제공한다. 예를 들어, printf()는 다양한 유형의 데이터를 터미널에 적합한 문자열 출력으로 변환한다.

2.입력과 출력에 버퍼(buffer)를 사용한다. 즉, 정보가 한번에 한바이트씩 전달되지 않고, 큰 덩어리(일반적으로 한번에 512바이트 또는 그이상)로 전달된다.

 

버퍼를 사용

프로그램이 파일을 읽을 때, 한 덩어리의 데이터가 버퍼(중간 저장영역)로 복사된다. 이와 같은 버퍼링은 데이터 전송속도를 크게 증가시킨다. 그러고 나면 프로그램은 버퍼에 들어있는 개별적인 바이트들을 조사할 수 있다. 버퍼링은 무대 뒤에서 은밀하게 이루어진다. 그래서 사용자에게는 문자 단위로 입출력이 이루어지는 것처럼 보인다.

 

exit()함수는 열려있는 모든 파일들을 닫으면서 프로그램을 종료시킨다. 일반적으로 프로그램이 정상적으로 종료되는 경우에는 0을 전달하고, 비정상적으로 종료되는 경우에는 0이아닌 값들을 전달한다. 실패의 여러 원인들을 서로 구별하기 위해 서로다른 종료값들을 사용할 수 있다.

 

ANSI C표준은 정상적인 종료를 나타내기 위해 값 0 또는 매크로 EXIT_SUCCESS 를 사용할 것과, 비정상적인 종료를 나타내기 위해 EXIT_FAILURE를 사용할 것을 요구한다. 이들 매크로는, exit() 프로토타입과 함께, stdlib.h 헤더파일에 있다.

 

fopen()은 파일을 여는 함수이다. 이 함수는 stdio.h에 선언되어 있다. 첫번째 전달인자는 열려고 하는 파일의 이름이다. 좀더 정확하게 말하자면 파일이름을 가지고있는 문자열의 주소이다. 두번째 전달인자는 파일을 여는데 사용할 모드를 지정하는 문자열이다. C라이브러리는 여러가지 모드 문자열을 제공한다.

 

fopen()의 모드 문자열

 

모드문자열                                                                          의미

    "r"                       읽기위해 파일을 텍스트 모드로 연다.

 

   "w"                       쓰기 위해 파일을 텍스트 모드로 연다. 파일이 이미 존재하면 파일 길이를 0으로 만든다.                                         파일이 없으면 새 파일을 만든다.

 

   "a"                       쓰기위해 파일을 텍스트 모드로 연다. 파일이 이미 존재하면 그 파일 끝에 덧붙인다. 파일이                                     없으면 새파일을 만든다.

 

  "r+"                      갱신하기 위해(즉, 읽고 쓰기 위해)파일을 텍스트 모드로 연다.

 

  "w+"                     갱신하기 위해(즉, 읽고 쓰기위해)파일을 텍스트 모드로 연다. 파일이 이미 존재하면 파일길이를                                0으로 만든다. 파일이 없으면 새 파일을 만든다.

 

  "a+"                     갱신하기 위해(즉, 읽고 쓰기 위해)파일을 텍스트 모드로 연다. 파일이 이미 존재하면 그 파일의                                끝에 덧붙인다. 파일이 없으면 새파일을 만든다. 읽기는 전체를 읽을 수 있지만 쓰기는 끝에                                      덧 붙일수만 있다.

 

"rb","wb","ab","ab+"   텍스트 모드가 아닌 바이너리 모드로 동작한다는 것을 제외하고, 앞의 모드들과 같다.

"a+b","wb+","w+b"

"rb+","r+b"

 

"wx","wbx","w+x",      파일이 이미 존재하면 오픈하는것을 실패한다는 것을 제외하고 non-x와 같다.

"wb+x","w+bx"

 

 

728x90

'Programming > C' 카테고리의 다른 글

C언어 공부 28  (0) 2019.06.12
C언어 공부 27  (0) 2019.06.12
C언어 공부 25  (0) 2019.06.11
프로그래밍 연습 10  (0) 2019.06.08
프로그래밍 연습 9  (0) 2019.06.02
728x90

파일입출력

 

파일들은 프로그램, 문서, 데이터, 서식, 그래픽, 그밖에도 수없이 많은 종류의 정보를 저장하는데 사용된다.

 

파일(file)은 일반적으로 이름이 붙어있는 디스크 상의, 즉 솔리드 스테이트 디바이스(고체 전기가 흐르는 전자 디바이스로 된 고체 상태 장치)의 어떤 영역이다.

 

운영체제 입장에서 볼때 파일은 조금 복잡하다. 예를들어, 하나의 커다란 파일이 여러영역에 나뉘어 저장되어 있을 수도 있다. 또는 어떤 종류의 파일인지 운영체제가 판단할 수 있는 부가적인 데이터가 파일 안에 들어있을 수도 있다.

 

C는 파일을, 각 바이트를 개별적으로 읽을 수 있는, 연속적인 바이트들의 시퀀스로 인식한다. 이것은 C의 성장 배경이였던 Unix 환경에서의 파일 구조와 일치한다. 다른 환경들은 이 모델과 정확히 일치하지 않을수도 있기 때문에, ANSI C는 파일의 두가지 인식 형식을 제공한다. 즉 텍스트 인식과 바이너리 인식을 제공한다.

 

모든 파일 컨텐츠는 2진법의(바이너리)형태 (0과 1의)이다. 그러나 만일 파일이 C문자열만큼 많은 문자를 표현하기 위해 캐릭터용으로 2진 코드를 사용한다면 그것은 텍스트 파일이다. 텍스트 컨텐츠가 있는것이다.

 

파일안에 있는 2진값들이 기계어 코드 또는 수치데이터(int 값 long값 등등) 또는 이미지나 음악 인코딩을 표현한다면 컨텐츠는 바이너리이다.

 

Unix는 두 종류의 컨텐츠에 같은 파일 포맷을 사용한다. C와 Unix모두 텍스트에 행 바꿈을 나타낼때 \n(개행문자)를 사용한다.

 

텍스트 파일을 처리하기 위한 일부 규칙을 가져오기 위해, C는 파일에 엑세스하는 두가지 방식, 즉 텍스트(text)모드와  바이너리(binary)모드를 제공한다. 바이너리 모드에서, 프로그램은 파일의 각 바이트에 그리고 모든 바이트에 접근할 수 있다.

 

텍스트 모드에서는 프로그램이 인식하는 내용과 파일에 있는 내용이 다를 수 있다.

 

텍스트 파일을 반드시 텍스트 관점으로만 사용해야 하는 것은 아니다. 같은 파일을 바이너리 관점으로도 사용할 수 있다.

 

C가 바이너리 관점과 텍스트 관점을 모두 제공하지만 이 관점들은 이상적으로 적용될 수 있다. 언급된 바와 같이, Unix는 하나의 파일 구조만 사용하므로 Unix에서는 구현할 때 두가지 관점들이 동일해진다. 그리고 이것은 Linux도 마찬가지다.

 

728x90

'Programming > C' 카테고리의 다른 글

C언어 공부 27  (0) 2019.06.12
C언어 공부 26  (0) 2019.06.11
프로그래밍 연습 10  (0) 2019.06.08
프로그래밍 연습 9  (0) 2019.06.02
프로그래밍 연습 8  (0) 2019.06.02
728x90

p597-1
p597-3
p597-6
p598-8
p598-10
p599-12
p599-14
p599 - 16

728x90

'Programming > C' 카테고리의 다른 글

C언어 공부 26  (0) 2019.06.11
C언어 공부 25  (0) 2019.06.11
프로그래밍 연습 9  (0) 2019.06.02
프로그래밍 연습 8  (0) 2019.06.02
rand, srand 코드  (0) 2019.06.01
728x90

p515 -1
p515-3
p515-5
p516-11

 

728x90

'Programming > C' 카테고리의 다른 글

C언어 공부 25  (0) 2019.06.11
프로그래밍 연습 10  (0) 2019.06.08
프로그래밍 연습 8  (0) 2019.06.02
rand, srand 코드  (0) 2019.06.01
C언어 공부 24  (0) 2019.05.31
728x90

p447 - 1
p447-3
p447-5
p448 -8
p448-10 입력값을 입력진수값으로 변환

728x90

'Programming > C' 카테고리의 다른 글

프로그래밍 연습 10  (0) 2019.06.08
프로그래밍 연습 9  (0) 2019.06.02
rand, srand 코드  (0) 2019.06.01
C언어 공부 24  (0) 2019.05.31
C언어 공부 23  (0) 2019.05.31
728x90

728x90

'Programming > C' 카테고리의 다른 글

프로그래밍 연습 9  (0) 2019.06.02
프로그래밍 연습 8  (0) 2019.06.02
C언어 공부 24  (0) 2019.05.31
C언어 공부 23  (0) 2019.05.31
C언어 공부 22  (0) 2019.05.31
728x90

변수 선언에서 const 키워드는 그 변수를 대입 연산, 증가 연산, 감소 연산으로 값을 변경할 수 없는 변수로 만든다.

 

단순한 변수나 배열을 선언할 때 const 키워드를 사용하는 것은 아주 쉽다. 포인터의 경우에는 좀더 복잡하다. 왜냐하면 포인터 자체를 const로 만드는 것과, 포인터가 가리키는 값을 const로 만드는 것을 구별해야 하기 때문이다.

 

const를 *의 왼쪽 어딘가에 넣으면 그 데이터를 상수로 만든다.

const를 *의 오른쪽에 넣으면 그 포인터 자체를 상수로 만든다.

 

헤더파일 방식의 장점은, 하나의 파일에 정의 선언들을 사용하고, 다른 파일들에 참조 선언들을 사용해야 한다는 것을 기억할 필요가 없다는 것이다. 단지 모든 파일들이 동일한 헤더파일을 포함하면 된다. 헤더파일 방식의 단점은, 데이터가 중복된다는 것이다.

 

volatile 한정자는, 어떤 변수가 프로그램이 아닌 대행자에 의해 그 값이 변경될 수 있다고 컴파일러에게 알린다. 일반적으로 그것은 하드웨어 주소에 또는 동시에 실행되는 여러 프로그램들이 공유하는 데이터에 사용된다.

 

restrict 키워드는 컴파일러가 특정 유형의 코드를 최적화 할 수 있도록 허용함으로써 계산 능력을 향상 시킨다. restrict 키워드는 포인터에만 적용할 수 있다. 그것은 그 포인터가 어떤 데이터 객체에 접근하는 유일한 최초 수단이라는 것을 나타낸다.

 

double stick(double ar[static 20]);

static을 이와같이 사용하는 것을, 함수 호출에 사용하는 실 전달인자가 최소한 20개의 원소를 가지는 배열의  첫번째 원소를 가리키는 포인터여야 한다는 것을 나타낸다. 이렇게 하는 목적은, 컴파일러가 그 정보를 사용하여 함수의 코드를 최적화 할 수 있도록 하기 위해서 이다.

 

정적 메모리의 양은 컴파일 할 때 결정되고, 정적 데이터는 프로그램이 메모리에 적재될때 함께 적재된다.

 

자동변수는 프로그램의 실행 도중에 할당되고 해제된다. 그래서 자동변수가 사용하는 메모리의 양은 프로그램이 실행하는 동안 수시로 변한다.

 

C의 저장 클래스

1.자동(Auto matic) - 저장 클래스 지정자 없이 또는 auto 저장 클래스 지정자를 사용하여 블록안에(또는 함수 머리에 있는 매개 변수로) 선언된 변수는 자동 저장 클래스에 속한다. 자동 변수는 자동 수명, 블록 범위, 무연계를 가진다. 초기화 하지 않으면, 자동 변수의 값은 결정되지 않는다.

 

2.레지스터(register) - register 저장 클래스 지정자를 사용하여 블록안에(또는 함수 머리에 있는 매개변수로) 선언된 변수는 레지스터 저장 클래스에 속한다. 레지스터 변수는 자동수명, 블록범위, 무연계를 가진다. 레지스터 변수의 주소는 얻을 수 없다.

 

정적 무연계(static, no linkage) - static 저장 클래스 지정자를 사용하여 블록안에 선언된 변수는 무연계 정적 저장 클래스에 속한다. 이 블록범위 정적 변수는 정적 수명, 블록 범위, 무연계를 가진다. 컴파일 될 때 단 한번 초기화 된다. 명시적으로 초기화 하지 않으면, 모든 바이트들이 0으로 설정된다.

 

정적 외부 연계(static, external linkage) - static 저장 클래스 지정자 없이 모든 함수들의 외부에 선언된 변수는 외부연계 정적 저장 클래스에 속한다. 외부연계 정적 변수는 정적 수명, 파일 범위, 외부 연계를 가진다. 컴파일 될 때 단 한번 초기화 된다. 명시적으로 초기화 하지 않으면, 모든 바이트들이 0으로 설정된다.

 

정적 내부 연계(static, internal linkage) - static 저장 클래스 지정자를 사용하여 모든 함수들의 외부에 선언된 변수는 내부연계 정적 저장 클래스에 속한다. 내부연계 정적 변수는 정적 수명, 파일 범위, 내부연계를 가진다. 컴파일 될 때 단 한번 초기화 된다. 명시적으로 초기화 하지 않으면, 모든 바이트들이 0으로 설정된다.

 

할당된 메모리는 malloc() (또는 관련 함수)에 의해 제공된다. 이 함수는 요청한 만큼의 바이트 수를 가지는 메모리 블록을 가리키는 포인터를 리턴한다. 이 메모리 블록은 free()함수를 호출하여 해제함으로써 재사용 할 수 있다. free() 함수는 그 메모리 블록의 주소를 전달인자로 사용한다.

 

const 데이터 형 한정자는 데이터 상수로 한정한다. 포인터에 const 한정자를 사용하면, 선언의 어느 위치에 const를 놓느냐에 따라 포인터 자체가 상수라고 나타내거나, 포인터가 가리키는 데이터가 상수라고 나타낼 수 있다.

 

volatile 데이터형 한정자는 프로그램이 아닌 다른 대행자에 의해 데이터가 변경될 수 있다는 것을 나타낸다. 이것을 사용하는 목적은, 사용하지 않을 경우에 컴파일러가 가정할 최적화를 피하라고 경고하는 것이다.

 

restrict 데이터형 한정자도 최적화를 위해서 제공된다. 포인터를 restrict로 한정하면, 그 포인터를 통해서만 데이터 블록에 접근할 수 있다.

728x90

'Programming > C' 카테고리의 다른 글

프로그래밍 연습 8  (0) 2019.06.02
rand, srand 코드  (0) 2019.06.01
C언어 공부 23  (0) 2019.05.31
C언어 공부 22  (0) 2019.05.31
C언어 공부 21  (0) 2019.05.30

+ Recent posts