Language/C

[C] C언어 개요 - 정의, 기초, 프로그래밍, 특징, 입출력 함수

재은초 2026. 6. 1. 22:35
728x90
반응형

C언어란?

  • C언어는 현재 사용하고 있는 거의 모든 컴퓨터 시스템에서 사용할 수 있는 프로그래밍 언어다.
  • 프로그래밍 언어란 컴퓨터의 시스템을 구동시키는 소프트웨어를 작성하기 위한 언어를 의미하는데, 이러한 프로그래밍 언어는 크게 저급 언어(low-level language)와 고급 언어(high-level language)로 나뉜다.
  • 저급 언어는 컴퓨터가 이해하기 쉽게 작성된 프로그래밍 언어로, 대표적인 언어로는 기계어(machine language)와 어셈블리어(assembly language) 등이 있다. 이 언어는 실행 속도가 매우 빠르지만, 사람이 배우기에는 매우 어려워 프로그램의 유지보수가 힘들다.
  • 고급 언어는 컴퓨터보다는 사람이 알기 쉽도록 작성된 프로그래밍 언어다. 고급 언어는 컴파일러나 인터프리터에 의해 기계가 이해 할 수 있는 언어로 번역되어 실행된다. 그래서 저급 언어보다는 상대적으로 실행 속도가 느리지만, 저급 언어에 비해 가독성이 높고 다루기가 쉽다.
  • C언어는 저급 언어와 고급 언어의 특징을 모두 가지고 있는 절차 지향 프로그래밍 언어(procedure-oriented programming language)다.

 

C언어의 역사

  • C언어는 1972년 벨 연구소의 켄 톰프슨(Kenneth Thompson)과 데니스 리치(Dennis Ritchie)가 유닉스(UNIX) 운영체제에서 사용하기 위해서 개발한 범용적인 고급 언어다.
  • A언어라고 불리는 ALGOL 60부터, CPL, BCPL을 거쳐, 켄 톰프슨이 B언어를 개발하게 된다. 이후 데니스 리치가 B언어를 좀 더 개선하여 지금의 C언어를 만든다.

 

C언어의 탄생 배경

  • C언어 이전에 유닉스 운영체제는 어셈블리어라는 저급 언어를 사용했다. 하지만 어셈블리어는 특정 하드웨어에 종속적인 언어여서, 이 언어로 작성된 프로그램은 다른 하드웨어로 이식할 수 없었다. 즉, 하나의 기능을 하는 프로그램을 CPU의 종류만큼 여러 번 작성해야만 했던 것이다. 따라서 이식성도 좋고 어셈블리어보다 쉬운 언어가 필요해졌고, 그래서 개발된 언어가 바로 C언어다.
  • 현재 널리 사용되는 모든 운영체제의 핵심은 대부분 C언어를 이용해 구현되어 있다. 이처럼 C언어는 시스템 프로그래밍에 가장 잘 어울리지만, 응용 프로그래밍에도 많이 사용되는 프로그래밍 언어다.

 

C언어의 특징

장점

  • C언어로 작성된 프로그램은 다양한 하드웨어로의 이식성이 좋다.
  • C언어는 절차 지향 프로그래밍 언어로, 코드가 복잡하지 않아 상대적으로 유지보수가 쉽다.
  • C언어는 저급 언어의 특징을 가지고 있으므로, 어셈블리어 수준으로 하드웨어를 제어할 수 있다.
  • C언어는 코드가 간결하여, 완성된 프로그램의 크기가 작고 실행 속도가 빠르다.

단점

  • C언어는 저급 언어의 특징을 가지고 있으므로, 자바와 같은 다른 고급 언어보다 배우기가 쉽지 않다.
  • C언어는 다른 언어와는 달리 시스템 자원을 직접 제어할 수 있으므로, 프로그래밍하는데 세심한 주의를 기울여야 한다.

 

C언어 표준

  • C언어는 1989년부터 ANSI(American National Standards Institute)에서 표준화 작업을 진행해왔다. 하지만 현재는 ISO/IEC(International Organization for Standardization / International Electrotechnical Commission)에서 표준화를 담당하고 있다.
  • C언어의 최신 표준은 ISO/IEC 9899:2011이며, 줄여서 C11이라고도 부른다.

 

C언어 프로그래밍

  • 프로그래밍이란 목적에 맞는 알고리즘으로부터 프로그래밍 언어를 사용하여 구체적인 프로그램을 작성하는 과정을 의미한다. 이렇게 작성된 프로그램은 먼저 실행 파일(executable file)로 변환되어야 실행할 수 있다.
  • C언어에서 실행 파일을 생성하는 순서
    • 소스 파일(source file)의 작성
      • 프로그래밍에서 가장 먼저 해야 할 작업은 바로 프로그램을 작성하는 것이다.
      • C언어를 사용하여 문법에 맞게 논리적으로 작성된 프로그램을 원시 파일 또는 소스 파일이라고 한다. C언어를 통해 작성된 소스 파일의 확장자는 .c 가 된다.
    • 선행처리기(preprocessor)에 의한 선행처리
      • 선행처리(preprocess)란 소스 파일 중에서도 선행처리 문자(#)로 시작하는 선행처리 지시문의 처리 작업을 의미한다.
      • 이러한 선행처리 작업은 선행처리기(preprocessor)가 수행한다. 선행처리기는 코드를 생성하는 것이 아닌, 컴파일하기 전 컴파일러가 작업하기 좋도록 소스를 재구성해주는 역할만 한다.
    • 컴파일러(compiler)에 의한 컴파일
      • 컴퓨터는 0과 1로 이루어진 이진수로 작성된 기계어만을 이해할 수 있다. 반면에 소스 파일은 개발자에 의해 C언어로 작성되므로, 컴퓨터는 그것을 바로 이해할 수 없다. 따라서 소스 파일을 컴퓨터가 알아볼 수 있는 기계어로 변환시켜야 하는데, 그 작업을 컴파일(compile)이라고 한다.
      • 컴파일은 컴파일러에 의해 수행되며, 컴파일이 끝나 기계어로 변환된 파일을 오브젝트 파일(object file)이라고 한다. 이러한 오브젝트 파일의 확장자는 .o 나 .obj 가 된다.
    • 링커(linker)에 의한 링크
      • 컴파일러에 의해 생성된 오브젝트 파일은 운영체제와의 인터페이스를 담당하는 시동 코드(start-up code)를 가지고 있지 않고 또한 대부분의 C 프로그램에서 사용하는 C 표준 라이브러리 파일도 포함되어 있지 않다.
      • 이때 하나 이상의 오브젝트 파일과 라이브러리 파일, 시동 코드 등을 합쳐 하나의 파일로 만드는 작업을 링크(link)라고 한다. 링크는 링커(linker)에 의해 수행되며, 링크가 끝나면 하나의 새로운 실행 파일이나 라이브러리 파일이 생성된다.
      • 이처럼 여러 개의 소스 파일을 작성하여 최종적으로 링크를 통해 하나의 실행 파일로 만드는 것을 분할 컴파일이라고 한다.
    • 실행 파일(executable file)의 생성
      • 소스 파일은 선행처리기, 컴파일러 그리고 링커에 의해 위와 같은 과정을 거쳐 실행 파일로 변환된다.
      • 최근 사용되는 개발 툴은 대부분 위에서 소개한 선행처리기, 컴파일러, 링커를 모두 내장하고 있으므로, 소스 파일에서 한 번에 실행 파일을 생성해 준다. 이렇게 생성된 실행 파일의 확장자는 .exe 가 된다.

https://www.tcpschool.com/c/c_intro_programming

 

 

C 프로그램의 특징

  • C 프로그램의 기본 단위는 함수다.
    • C 프로그램은 하나 또는 그 이상의 함수(function)로 이루어진다.
    • 또한, C언어로 구현되는 모든 프로그램은 반드시 main() 함수를 가지고 있어야 한다. C 프로그램이 실행되면 컴퓨터는 제일 먼저 main() 함수를 찾아서 호출하기 때문이다.
#include <stdio.h>
#define TEXT "Welcome to C Programming!!"

int main()
{
    return 0;     // main() 함수의 모든 명령문을 수행한 후에는 0을 반환함.
}
  • 함수 내의 각 명령문은 세미콜론(;)으로 끝나야 한다.
    • 함수는 언제나 기능을 가지고 있어야 한다. C언어에서 이러한 기능을 정의하기 위해 사용되는 문장을 명령문(statement)이라고 한다. 함수 내의 명령문은 언제나 위에서부터 아래로 순차적으로 실행되며, 언제나 세미콜론(;)으로 끝나야 한다.
printf("C언어"); // 정상적으로 출력
printf("C언어")  // 오류가 발생
  • C언어는 대소문자를 구분한다.
    • C언어에서 변수나 함수의 이름을 작성할 때나 키워드나 예약어 등을 사용할 때는 대소문자를 정확히 구분하여 사용해야 한다.
printf("C언어");  // 정상 출력
Printf("C언어");  // 오류 발생
  • C언어는 자유 형식(free-format)을 허용한다.
    • C언어에서는 문법만 맞으면 여러 개의 명령문을 한 줄에 쓸 수도 있고, 하나의 명령문을 여러 줄에 나누어 쓸 수도 있다.
    • 하지만 프로그램의 구조를 한눈에 파악할 수 있도록, 될 수 있으면 들여쓰기 등을 잘 활용해 보기 좋게 작성하는 것이 좋다.
int func() { printf("C언어는 재밌어요!"); }
int func()
{
    printf("C언어는 재밌어요!");
}

 

C 프로그램의 구조

  • 간단한 C 프로그램의 기본 구조는 다음 예제와 같다. 언제나 다음과 같이 구성되는 것은 아니지만, 대부분의 C 프로그램이 이와 비슷한 형태로 구성된다.
#include 문
#define 문

int main(void)
{
    명령문;
    ...
    return 문;
}
#include <stdio.h>
#define TEXT "Welcome to C Programming!!"  

int main()
{
    printf(TEXT);
    return 0;
}

// Welcome to C Programming!!

주석(comments)

  • C언어 주석의 장점은 프로그램 내의 어디에나 올 수 있다는 점이다.
// 한 줄 주석

/* 여러
   줄
   주석 */
/* 여러 줄
    // 이렇게 두 줄 주석 안에 또 다른 한 줄 주석을 삽입할 수 있습니다.
주석입니다. */
  • 하지만 다음 예제처럼 여러 줄 주석 안에 또 다른 여러 줄 주석은 중첩해서 삽입할 수 없다.
/* 여러 줄
   /* 또 다른 여러 줄 주석입니다. */
주석입니다. */

 

C언어 표준 입출력 함수

  • 사용자가 프로그램과 대화하기 위해 사용하는 함수를 입출력 함수 또는 I/O 함수라고 한다.
  • printf() 함수와 scanf() 함수는 C언어 표준 입출력 함수 중에서도 가장 많이 사용되는 대표적인 입출력 함수다.

printf() 함수

  • printf() 함수는 C언어의 표준 출력 함수로, 여러 종류의 데이터(data)를 다양한 서식에 맞춰 출력할 수 있게 해준다.
  • printf() 함수의 f는 formatted의 약자이며, 서식화된 출력을 지원한다는 의미다. 이 함수는 출력할 데이터를 어떤 서식에 맞춰 출력할지 서식 지정자(format specifier)를 통해 직접 지정할 수 있다.
#include <stdio.h>
int printf(const char * restrict format, ...);
  • 아래 예제에서 int형 데이터를 나타내기 위해서 '%d'라는 서식 지정자를 사용했고 줄 바꿈은 '\n'라는 이스케이프 시퀀스를 사용하여 표현하고 있다.
printf("printf() 함수는 서식 지정자를 통해 출력할 데이터의 서식을 지정할 수 있어요!\n");
printf("변수에 저장된 숫자는 %d입니다.", 10);

// printf() 함수는 서식 지정자를 통해 출력할 데이터의 서식을 지정할 수 있어요!
// 변수에 저장된 숫자는 10입니다.

참고. 이스케이프 시퀀스(escape sequence)

  • 이스케이프 시퀀스는 프로그램의 결과가 화면에 출력될 때 사용하게 될 특수한 문자를 위해 만들어졌다.
  • 이스케이프 시퀀스 중에서 '\f'와 '\v'는 프린터로 출력할 때에만 의미를 가진다.

https://www.tcpschool.com/c/c_intro_printf

printf("C언어에서 사용하는 \"특수 문자\"에는 여러가지가 있습니다.\n");
printf("\t특수 문자의 바로 앞에는 언제나 \\가 와야 합니다.");

// C언어에서 사용하는 "특수 문자"에는 여러가지가 있습니다.
//   특수 문자의 바로 앞에는 언제나 \가 와야 합니다.

참고. 서식 지정자(format specifier)

  • printf() 함수에서는 이러한 서식 지정자를 통해 출력할 데이터의 서식을 사용자가 직접 지정할 수 있다.

https://www.tcpschool.com/c/c_intro_printf

printf("%%c를 사용한 결과 : %c\n", 'a');            // 문자
printf("%%s를 사용한 결과 : %s\n", "즐거운 C언어"); // 문자열  

printf("%%f를 사용한 결과 : %f\n", 0.123456);
printf("%%f를 사용한 결과 : %f\n", 0.123456789);    // 소수점 6자리까지만 표현  

printf("%%o를 사용한 결과 : %o\n", 123);            // 8진 정수
printf("%%x를 사용한 결과 : %x\n", 123);            // 16진 정수  

printf("%%g를 사용한 결과 : %g\n", 0.001234);       // 값에 따라 %f나 %e
printf("%%g를 사용한 결과 : %g\n", 0.00001234);     // 값에 따라 %f나 %e
printf("%%G를 사용한 결과 : %G\n", 0.000001234);    // 값에 따라 %f나 %E

// %c를 사용한 결과 : a
// %s를 사용한 결과 : 즐거운 C언어
// %f를 사용한 결과 : 0.123456
// %f를 사용한 결과 : 0.123457
// %o를 사용한 결과 : 173
// %x를 사용한 결과 : 7b
// %g를 사용한 결과 : 0.001234
// %g를 사용한 결과 : 1.234e-05
// %G를 사용한 결과 : 1.234E-06
  • 여러 개의 서식 지정자를 동시에 사용하여, 여러 개의 데이터에 서로 다른 서식을 지정해 출력할 수 있다. 단, 이때 서식 지정자의 순서와 타입은 출력할 데이터의 순서와 타입과 반드시 일치해야 한다.
printf("저장된 정수는 %d이며, 저장된 문자열은 %s입니다.\n", 123, "C언어");

// 저장된 정수는 123이며, 저장된 문자열은 C언어입니다.
  • 서식 지정자의 '%'기호와 타입을 나타내는 영문자 사이에 숫자를 추가하여 출력되는 필드의 폭을 직접 설정할 수 있다.
  • 내부의 숫자는 오른쪽 정렬이 기본이며, 숫자 앞에 '-'기호를 붙이면 왼쪽 정렬로 변경된다.
  • 또한, 숫자 앞에 '+'기호를 붙이면 숫자를 오른쪽 정렬한 상태에서 양수에는 '+'기호를, 음수에는 '-'기호를 붙여서 출력한다. 이때 소수 부분의 숫자는 출력되는 소수의 자릿수를 명시한다.
printf(" %%d를 사용한 결과 : |%d|\n", 123);
printf(" %%7d를 사용한 결과 : |%7d|\n", 123);
printf(" %%+7d를 사용한 결과 : |%+7d|\n", 123);
printf(" %%-7d를 사용한 결과 : |%-7d|\n\n", 123);

printf(" %%f를 사용한 결과 : |%f|\n", 1.23);           // 기본 실수 출력 (소수 6자리)
printf(" %%.1f를 사용한 결과 : |%.1f|\n", 1.23);       // 소수점 이하 1자리
printf(" %%7.2f를 사용한 결과 : |%7.2f|\n", 1.23);     // 최소 폭 7칸 + 소수점 이하 2자리
printf("%%+7.2f를 사용한 결과 : |%+7.2f|\n", 1.23);    
printf("%%-7.2f를 사용한 결과 : |%-7.2f|\n\n", 1.23);

// %d를 사용한 결과 : |123|
// %7d를 사용한 결과 : |    123|
// %+7d를 사용한 결과 : |   +123|
// %-7d를 사용한 결과 : |123    |

// %f를 사용한 결과 : |1.230000|
// %.1f를 사용한 결과 : |1.2|
// %7.2f를 사용한 결과 : |   1.23|
// %+7.2f를 사용한 결과 : |  +1.23|
// %-7.2f를 사용한 결과 : |1.23   |

scanf() 함수

  • scanf() 함수는 C언어의 표준 입력 함수로, 사용자로부터 다양한 데이터를 다양한 서식에 맞춰 입력받을 수 있게 해준다.
  • scanf() 함수의 f는 formatted의 약자이며, 서식화된 입력을 받는다는 의미다. 이 함수는 입력받은 데이터를 어떤 서식으로 변환할지 서식 지정자(format specifier)를 통해 직접 지정할 수 있다.
#include <stdio.h>
int scanf(const char * restrict format, ...);
  • C언어에서 데이터를 입력받으려면 입력받고자 하는 데이터의 타입에 해당하는 크기의 메모리를 우선 할당받아야 한다. 이처럼 데이터를 저장하기 위해 프로그램에 의해 이름을 할당받은 메모리 공간을 변수(variable)라고 한다.
  • 아래 예제에서 scanf() 함수에 포함된 '&'기호는 주소 연산자(&)라고 한다. 이 주소 연산자는 입력받은 데이터를 뒤에 나오는 변수에 저장하라는 의미다.
#include <stdio.h>

int main(void)
{
    int num01, num02;

    printf("첫 번째 정수를 입력하세요 : ");
    scanf("%d", &num01);
    printf("두 번째 정수를 입력하세요 : ");
    scanf("%d", &num02);

    printf("입력하신 두 정수의 합은 %d입니다.\n", num01 + num02);
    return 0;
}

// 첫 번째 정수를 입력하세요 : 10
// 두 번째 정수를 입력하세요 : 20
// 입력하신 두 정수의 합은 30입니다.
  • 여러 개의 서식 지정자를 동시에 사용하여, 여러 데이터를 서로 다른 서식으로 한 번에 입력받을 수 있다. 단, 이때에는 서식 지정자의 순서와 저장할 변수의 순서가 반드시 같아야 한다.
  • 입력받는 데이터의 구분은 공백(줄 바꿈, 탭, 띄어쓰기 등)을 기준으로 삼는다.
#include <stdio.h>

int main(void)
{
    int num01, num02;

    printf("두 개의 정수를 입력하세요 : ");
    scanf("%d %d", &num01, &num02);

    printf("입력하신 두 정수를 8진수로 나타내면 %o와 %o가 되고,\n", num01, num02);
    printf("입력하신 두 정수를 16진수로 나타내면 %x와 %x가 됩니다.\n", num01, num02);
    return 0;
}

// 두 개의 정수를 입력하세요 : 10 20
// 입력하신 두 정수를 8진수로 나타내면 12와 24가 되고,
// 입력하신 두 정수를 16진수로 나타내면 a와 14가 됩니다.
  • scanf() 함수로 float형 실수를 입력받을 때는 서식 지정자로 '%f'를 사용하면 된다. 하지만 double형 실수를 입력받을 때는 printf() 함수에서처럼 '%f'를 사용하면 안 된다. scanf() 함수로 double형 실수를 입력받을 때는 반드시 '%lf' 서식 지정자를 사용해야 정확한 값으로 입력받을 수 있다.
#include <stdio.h>  

int main(void)
{
    float num01;
    double num02;

    printf("두 개의 실수를 입력하세요 : ");
    scanf("%f %f", &num01, &num02);
    printf("입력하신 두 실수는 %f와 %f입니다.\n", num01, num02);
    printf("입력받은 두 실수 중 두 번째 double형 변수에는 전혀 다른 값이 저장되었습니다.\n\n");

    printf("다시 한 번 두 개의 실수를 입력하세요 : ");
    scanf("%f %lf", &num01, &num02);
    printf("입력하신 두 실수는 %f와 %f입니다.\n", num01, num02);
    printf("이번에는 두 실수 모두 제대로 저장되었습니다.\n");
    return 0;
}

// 두 개의 실수를 입력하세요 : 1.2 3.4
// 입력하신 두 실수는 1.200000와 0.000000입니다.
// 입력받은 두 실수 중 두 번째 double형 변수에는 전혀 다른 값이 저장되었습니다.

// 다시 한 번 두 개의 실수를 입력하세요 : 1.2 3.4
// 입력하신 두 실수는 1.200000와 3.400000입니다.
// 이번에는 두 실수 모두 제대로 저장되었습니다.

 

Reference

728x90
반응형