C 라이브러리 함수 중 ftell()을 소개하면서 말씀 드린 내용입니다만 함수를 호출에서 인수에 사용하는 함수를 잘못 이해하면 아주 엉뚱한 결과가 나오면서 보이지 않는 버그가 되기 때문에 강좌 게시판에도 올립니다.

아래에 abc()함수를 호출하면서 fun1()과 fun2()를 호출하고 있습니다.

abc( fun1(), fun2());

abc() 를 호출하기 위해서는 fun1()과 fun2()를 실행하고 각각의 반환된 값을 먼저 구한 후에야 abc()를 호출하게 됩니다. 그렇다면 여기서 fun1()이 먼저 실행될까요? 아니면 fun2()가 먼저 실행될까요?

C에서는 우측에서 좌측으로 실행해 갑니다. 그러므로 fun2()이 실행되고난 후에 fun1()이 실행됩니다. fun1() 과 fun2()이 서로 전혀 관계가 없다면 문제가 없지만 서로 실행에 영향을 미친다면 문제가될 수 있습니다. 또한 눈에 띄지 않는 버그가 되기 쉽습니다.

ftell의 예를 보겠습니다. 이 예에서는 파일을 읽어서 파일의 첫 번째 문자부터 위치와 함께 문차를 차례로 출력해 주는 예제입니다.

#include <stdio.h>

int main( void)
{
   FILE *fp;
   int   ndx;

   fp = fopen( "./main.c", "r");

   for ( ndx = 0; ndx < 5; ndx++)
   {
      printf( "pointer = %d  char = %cn", ftell( fp), fgetc( fp));
   }

   fclose( fp);

   return 0;
}

그냥 보기에는 아무 이상이 없습니다. 당연히 컴파일부터 링크까지 아무 이상이 없고 실행도 됩니다만 실은 오류가 있습니다. ftell(fp) 로 출력할 문자의 위치를 알려 주려했지만 C에서는 오른쪽 함수부터 먼저 실행이 되기 때문에 ftell()보다 fgetc()가 먼저 호출됩니다.

그러므로 ftell()은 현재 출력되는 문자의 위치가 아니라 다음 문자 위치를 알려 주게 됩니다. 제대로 작성된 예제는 아래와 같습니다.

#include <stdio.h>

int main( void)
{
   FILE *fp;
   int   ndx;

   fp = fopen( "./main.c", "r");

   for ( ndx = 0; ndx < 5; ndx++)
   {
      printf( "pointer = %d",  ftell( fp));    // ftell()을 먼저 실행
      printf( "    ");
      printf( "char = %cn" , fgetc( fp));
   }

   fclose( fp);

   return 0;
}

저도 여러 행으로 나누는 것 보다는 한 개의 행으로 간결하게 작성하는 것을 좋아합니다. 가급적 변수를 사용하지 않으려 노력합니다만, 버그를 생성하는 것 보다는 차라리 변수를 사용하는 것이 좋더군요. 이런 이유로 아래와 같은 식으로 프로그램을 작성하고 있습니다.

#include <stdio.h>

int main( void)
{
   FILE *fp;
   char  ndx_byte;
   char  chr_byte;
   int   ndx;

   fp = fopen( "./main.c", "r");

   for ( ndx = 0; ndx < 5; ndx++)
   {
      ndx_byte = ftell( fp);
      chr_byte = fgetc( fp);
      printf( "pointer = %d   char = %cn",  ndx_byte, chr_byte);
   }

   fclose( fp);

   return 0;
}

그러나 변수를 남발하지 않으려고 노력하죠. ^^

태그: *gcc *C언어 *함수