IT 이야기/IT Tech

UNIX C를 10년만에 사용, 실수하기 쉬운 것들

필넷 2009. 12. 18. 14:26
반응형

올해초 몸담고 있는 직장에서 부서를 옮기면서 그 동안 하던 일과는 전혀 다른 업무를 하게되었다.
그래서 자그만치 10년만에 UNIX 환경에서 C와 JAVA를 사용하게 되었다. 10년이면 강산이 한번 변할 시기이다. 하물며 IT쪽은 10년이면 부모도 몰라볼 시간(?)이라고 할 수 있다.

아무튼 JAVA는 ver 1.0 시절에 사용했었고, UNIX 환경에서 C 프로그래밍은 대학시절에나 다루어보던 언어다.
그동안 다른 업무를 했어도 객체지향언어는 계속 사용해왔기에 JAVA는 부담없는데, UNIX환경에서 C를 사용하려니 많~이 생소하다. ㅋ
몇달전 즈음에 올린 fork() vs vfork() 라는 글과 socketpair과 pipe를 통한 프로세스간 통신의 차이점 이라는 글도 새롭게 UNIX C에 대한 기억을 더듬다 올린 글이다.

어이없는 실수들...


10년만에 UNIX C를 사용하면서 코딩을 하다보니 어이없는 실수들을 하고는 에러를 잡느라 갖은 고생을 하기도 한다.
몇가지 예를 들자면...

sizeof() vs strlen()

차이점을 이야기 하기에 앞서서 우선 sizeof(exp)는 함수가 아니고 연산자이다. sizeof(exp)는 exp의 크기를 바이트 단위로 알려주는 연산자이다.
착각하기 쉬운 점은 exp가 포인터 변수일 경우이다. 즉 아래의 예제를 보자.

char *t = "abcde"; printf("%d", sizeof(t));

위의 코드는 결과값이 '5'가 아닌 '4' 가 반환된다. 즉, 포인터 변수 t를 저장하기 위해서는 4바이트가 필요하다는 의미이다. 문자열의 길이를 계산하기 위해서는 strlen()을 사용해야 한다. strlen()의 함수 원형은 다음과 같다.

size_t strlen(const char *s)

문자열에서 '\0'를 만나기 전까지의 문자의 수를 계산해서 반환값으로 돌려준다.

포인터와 malloc() vs free()

malloc()와 free()의 함수 원형은 다음과 같다.

void *malloc(size_t size); void free(void *ptr);

객체지향 프로그래밍에 익숙해져 있는 사람에게 다시 C 언어의 포인터를 사용한다는 것은 참으로 부담스러운 일이다. 가급적 포인터를 사용안려고 노력해도 안할 수가 없는 언어가 바로 C언어이다.

포인터 변수를 선언하고 malloc을 이용해서 동적할당(Dynamic Assignment)을 했다면, malloc()의 반환값이 void 포인터형 이므로 원하는 데이터 타입으로 변환해 줄 필요가 있으며 해당 변수를 다 사용하고 난 뒤에는 free()를 이용해서 메모리를 해제해주어야 한다. 그렇지 않으면 어딘가에서 슬금슬금 메모리가 누수되다가 core dump를 내고 죽어버릴지도 모른다. --;

fwrite() vs fprintf()

fwrite()와 fprinft()의 함수 원형은 다음과 같다.

int fwrite(void *buf, int size, int count, FILE *fp); 
int fprintf(FILE *fp, const char *format, ...);

fwrite()의 파라메터 buf는 파일에 저장할 데이터를 가리키는 메모리 영역에 대한 포인터이다. 그리고 size는 buf의 데이터 타입의 크기이며 count는 전체 buf의 데이터 크기이다. fprintf()의 파라메터 format는 출력할 데이터의 서식과 변수들의 나열이다.

fwrite()와 fprintf()의 주요 차이점은 하나는 이진모드(binary mode)와 텍스트모드(text mode)의 차이이다. 즉, fwrite()는 파일에 이진모드 형식으로 기록하며 fprintf()는 텍스트모드(문자열)로 기록한다는 것이다.

따라서 서버로 부터 이진모드의 특정 파일을 읽어와서 로컬에 저장하고자 한다면 fwrite()를 사용해야한다.

이 글은 스프링노트에서 작성되었습니다.

반응형