Первая программа: компиляция и запуск

Урок проводит через первую программу на C: что значит каждая строчка «Hello, world», как превратить текст в исполняемый файл командой gcc и запустить его.
Программа на C — это не скрипт. Прежде чем её запустить, исходный текст нужно скомпилировать: перевести в машинный код. Понять этот переход — половина дела.

Традиция программирования велит начинать с программы, которая выводит приветствие. Вот она целиком:

#include <stdio.h>

int main(void) {
    printf("Hello, world!\n");
    return 0;
}

Разберём построчно. #include <stdio.h> — директива препроцессора: она подключает заголовочный файл стандартной библиотеки ввода-вывода (standard input/output), где объявлена функция printf. Без этой строки компилятор не знал бы, что такое printf. Строка int main(void) объявляет функцию main — точку входа: с неё начинается выполнение любой программы на C. Слово int означает, что функция вернёт целое число, а void в скобках — что она не принимает аргументов.

Внутри фигурных скобок — тело функции. printf("Hello, world!\n") печатает текст; \n — это символ перевода строки. Наконец, return 0; возвращает операционной системе код 0 — условный сигнал «программа завершилась успешно». Любое ненулевое значение традиционно означает ошибку.

Как работает под капотом

Самое важное отличие C от Python: вы не запускаете .c-файл напрямую. Сначала компилятор превращает текст в исполняемый файл. Этот путь проходит несколько этапов.

hello.c  (ваш текст)
   |
   |  1. Препроцессор: вставляет содержимое stdio.h,
   |     раскрывает #include и макросы
   v
hello.i  (расширенный исходник)
   |
   |  2. Компилятор: переводит C в ассемблер
   v
hello.s  (ассемблерный код)
   |
   |  3. Ассемблер: переводит в объектный машинный код
   v
hello.o  (объектный файл)
   |
   |  4. Компоновщик (linker): связывает с библиотеками
   v
hello    (готовый исполняемый файл) -> запускаем!

Команда gcc по умолчанию проделывает все четыре шага за один вызов и отдаёт готовый исполняемый файл. Скомпилируем и запустим:

gcc hello.c -o hello
./hello
# Выведет: Hello, world!

Флаг -o hello задаёт имя выходного файла. Без него gcc создаст файл с именем a.out. Команда ./hello запускает получившуюся программу.

Частые ошибки

  • Забыли точку с запятой. В C каждый оператор заканчивается ;. Пропуск даёт ошибку компиляции, часто с указанием на следующую строку — сбивает с толку.
  • Забыли #include <stdio.h>. Компилятор пожалуется на неявное объявление printf.
  • Пытаются запустить .c-файл напрямую, как Python-скрипт. Файл нужно сначала скомпилировать.
  • Пишут \n как два отдельных символа в выводе — путают обратный слэш с обычным. \n — это управляющая последовательность, один символ перевода строки.

Best practices

  • Всегда компилируйте с предупреждениями: gcc -Wall -Wextra hello.c -o hello. Это ловит массу ошибок ещё до запуска.
  • Пишите именно int main(void), а не void main() — стандарт C требует, чтобы main возвращал int.
  • Возвращайте осмысленный код: 0 при успехе, иначе — ненулевое значение. Это позволяет другим программам понять, как завершилась ваша.

В C мы не можем запустить код прямо в браузере, поэтому интерактив дадим на Python: та же по смыслу программа, печатающая приветствие и «возвращающая» код завершения.

def main():
    print("Hello, world!")
    return 0   # 0 = успех, как в C

code = main()
print("Программа завершилась с кодом:", code)

Та же логика на Python ▶ — обратите внимание: смысл return 0 одинаков, но в Python нет шага компиляции, а в C он обязателен.

Что значит «собрать проект»

Программа из одного файла — это учебный случай. В реальных проектах исходники разбиты на десятки .c-файлов, каждый компилируется в свой объектный файл, а компоновщик связывает их вместе в один исполняемый. Чтобы не вызывать gcc вручную для каждого файла, используют системы сборки — make, CMake и другие: они описывают зависимости и пересобирают только изменённое. Понимать этапы из этого урока (препроцессор, компиляция, ассемблирование, компоновка) полезно именно для отладки сборки: ошибка «undefined reference» — это компоновщик не нашёл определение функции, а «implicit declaration» — компилятор не увидел прототип. Зная, на каком этапе что происходит, вы быстро находите причину.

Итоги

Первая программа на C показала четыре ключевые вещи: директиву #include, функцию main как точку входа, вывод через printf и код завершения return 0. Главное — запомнить, что C компилируется: путь от текста к запуску проходит через препроцессор, компилятор, ассемблер и компоновщик, и команда gcc делает это за один вызов.

Проверьте себя
1. Что делает директива #include <stdio.h>?
AЗапускает программу
BПодключает заголовочный файл с объявлениями стандартного ввода-вывода, включая printf
CПечатает текст на экран
DЗавершает программу с кодом 0
2. Что означает return 0 в конце main?
AПрограмма выведет число 0
BЭто обязательный текст, который ничего не значит
CПрограмма сообщает операционной системе, что завершилась успешно
DПрограмма перезапускается