C 언어

Mon, Nov 16 2020 08:05:02

업데이트: 2024.01.04

C 언어를 공부해야 하는 이유

1. 호환성이 좋고 기본적으로 성능이 좋습니다.

소스코드를 약간만 수정하여 다양한 시스템에서 돌릴 수 있습니다. 또한 각종 언어에서 c 로 만든 라이브러리를 호출하는 것이 가능합니다.

2. c 를 쓰는 곳이 많습니다.

운영체제, 응용 어플, 시스템 소프트웨어, 라이브러리 등이 c 언어로 만들어져 있는 것이 많습니다. c 언어 프로젝트가 매우 많아서 오픈소스 기여도 손쉽습니다. C 를 쓰는 곳이 많아서 일자리가 많습니다.

3. 한번 배워 놓으면 10년 20년 주구장창 써먹을 수 있습니다.

4. 취미로도 무지 좋은 언어입니다.

가량 오디오 DAC 만들 때에도 써먹을 수 있는 언어가 C 언어입니다. 그리고 입력기, 비디오 다운로도 등 시스템 어플 및 응용 어플 및 GUI 어플 제작이 가능합니다.

5. 각종 시험 및 책에 c 언어가 나옵니다.

수능 시험, 대학 시험, 정보처리기사 시험에 c 언어가 나오므로 학생이라면 반드시 c 언어를 공부해야 합니다. 또한 각종 책의 예제소스 c 소스가 나오기 때문에 c 를 모르면 책이나 블로그 글을 이해할 때 애로 사항이 생기게 됩니다.

가성비 최고의 언어가 바로 c 언어입니다.

#define

C 언어에서 #define 은 매크로 기능을 합니다.

#define C_MAX(a, b)  (((a) > (b)) ? (a) : (b))

C_MAX(1, 2) 라는 코드를 컴파일러는 (((1) > (2)) ? (1) : (2)) 이러한 코드로 치환합니다.

전역 변수

전역 변수는 자동으로 초기화됩니다.

static 변수

static 변수는 정적 변수를 의미합니다. static 으로 선언하면 초기값을 지정하지 않았을 경우 전역 변수든 지역 변수든 0 으로 초기화됩니다.

문자열 입력 받기

scanf 함수로 문자열을 입력 받기 위해서는 버퍼를 미리 설정해 두어야 하는데 예를 들어 버퍼 크기를 10바이트로 설정하면 10바이트보다 큰 문자열을 입력받으면 에러가 발생하게 됩니다. 이러한 이유 때문에 scanf 함수로 문자열을 받는 것은 좋지 않습니다. 리눅스, BSD 등의 POSIX 를 지원하는 운영체제에서는 getline 함수를 제공하므로 getline 함수를 사용하여 문자열을 입력 받으시면 되겠습니다.

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

/* 문자열 2개를 입력 받아서 출력 */
int main ()
{
  char    *line = NULL;
  size_t   linecap = 0;
  ssize_t  linelen;

  printf ("첫 번째 문자열을 입력하세요: ");
  if ((linelen = getline (&line, &linecap, stdin)) > 0)
    printf ("첫 번째 문자열: %s\n", line);

  printf ("두 번째 문자열을 입력하세요: ");
  if ((linelen = getline (&line, &linecap, stdin)) > 0)
    printf ("첫 번째 문자열: %s\n", line);

  free (line);
}

그러나 MS윈도우에는 getline 함수가 없을 것이므로 아래처럼 함수를 만들어서 사용하시면 되겠습니다.

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

/*
 * 컴파일 방법
 * cc -o exam exam.c
 * scanf 사용할 때 오퍼플로우 문제 때문에 scanf 를 쓰지 말라고 권고하는 추세임.
 * fread() 함수를 이용하여 stdin 으로부터 1문자씩 읽어서 realloc 로 가변 문자열을 만드는 방법임
 */
char *get_line_from_stdin ()
{
  char *buf = malloc (sizeof (char));
  int i = 0;

  fflush (stdout);
  fflush (stderr);

  while (fread (buf + i, sizeof (char), 1, stdin) == sizeof (char))
  {
    if (buf[i] == 10 || feof (stdin)) /* LF or CTRL+D */
      break;

    i = i + sizeof (char);
    buf = realloc (buf, sizeof (char) + i);
  }

  buf[i] = 0; /* null-terminated string */

  return buf;
}

int main (int argc, char **argv)
{
  char *str;

  printf ("type: ");
  str = get_line_from_stdin ();

  printf ("%s\n", str);

  free (str);

  return 0;
}

입력이 있으면 realloc 을 이용하여 버퍼 크기도 그에 따라 늘립니다. 가변 문자 배열입니다. CTRL+D 누르는 상황을 대비하여 feof() 로 체크합니다. buf[i] == 10 에서 10은 아스키문자를 십진수로 나타낸 것입니다. LF(line feed)가 10에 해당합니다. scanf 대신에 유용하게 사용할 수 있습니다.

Out Of Memory 메모리 부족 에러

메모리가 부족할 때 이러한 에러가 발생합니다. malloc 함수는 할당 실패하면 NULL을 반환하고 errnoENOMEM 으로 설정합니다. 그래서 아래처럼 NULL 체크를 해줘야 합니다.

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

int main ()
{
  void *mem;
  mem = malloc (1000 * 1000);

  if (!mem)
  {
    fprintf (stderr, "malloc failed: %s\n", strerror (errno));
    abort ();
  }

  return 0;
}

메모리 할당 실패의 원인은

  1. 물리적 메모리가 부족한 경우
  2. 메모리 누수가 발생하는 경우
  3. 잦은 메모리 할당과 해제로 인한 메모리 파편화

등이 원인일 수 있습니다.

1의 경우는 메모리를 증설해야할 것이며,
2의 경우는 메모리 누수가 발생하는 부분을 찾아서 버그를 해결해야 하며
3의 경우는 메모리 할당과 해제를 가급적 줄이도록 프로그래밍을 해야겠습니다.