Язык C и компилятор GCC

В этом посте рассказываю о языке C, этапах компиляции и полезных флагах GCC

Язык C: коротко о главном

Язык программирования С (си) — один из самых популярных и распространенных языков. Это компилируемый язык общего назначения со статической типизацией. Его разработал в 1969—1973 годах в компании Bell Labs программист Деннис Ритчи (Dennis Ritchie).

С нередко называют языком программирования «среднего уровня» или даже «низкого уровня». Он сочетает элементы языков высокого уровня с функциональностью и производительностью ассемблера. Работает близко к аппаратной части компьютера. Это позволяет манипулировать данными на низком уровне и использовать высокоуровневые конструкции для управления работой программы.

Изначально С предназначался для написания операционной системы Unix. Позже основной сферой применения стало системное программирование: создание операционных систем, драйверов, утилит, антивирусов и др. Linux большей частью написан на Си.

Си — компилируемый язык. Компилятор переводит исходный код в исполняемый файл с набором машинных инструкций. Платформы отличаются, поэтому скомпилированную программу нельзя просто перенести с одной платформы на другую и там запустить. На уровне исходного кода программы на Си переносимы. Компиляторы, библиотеки и инструменты разработки есть почти под все распространенные платформы. Поэтому один и тот же исходный код на Си можно компилировать в приложения под эти платформы.

Основные особенности Си

  • Универсальность — один и тот же код можно скомпилировать почти на каждой платформе (при наличии для нее компилятора).
  • Высокая скорость исполнения.
  • Компактность — небольшой размер выходных скомпилированных файлов.

Что такое GCC

GCC (GNU Compiler Collection) — это набор компиляторов и сопутствующих инструментов. В него входят фронтенды для C, C++, Objective-C, Fortran, Ada, Go и других языков. На практике команда gcc — это драйвер, который управляет этапами сборки.

Когда вы запускаете gcc main.c -o app, драйвер последовательно запускает препроцессор, компилятор, ассемблер и линковщик. Этими этапами можно управлять через флаги: -E (только препроцессор), -S (до ассемблера), -c (до объектного файла), затем линковка в исполняемый файл.

GCC ценят за переносимость, зрелую экосистему и очень подробную документацию. Если нужна точная семантика любого флага, лучше сразу сверяться с официальным manual.

Официальная документация GCC

Установка GCC

macOS

brew update
brew install gcc
gcc --version

Если Homebrew ещё не установлен, сначала поставьте его с официального сайта: brew.sh.

Linux

sudo apt update
sudo apt install build-essential gcc gdb make
gcc --version

Пакет build-essential ставит базовый набор инструментов для сборки C/C++ на Ubuntu/Debian (включая gcc, g++, make и заголовки libc).

Документация и пакеты: build-essential в Ubuntu Packages, gcc в Ubuntu Packages.

Windows

На Windows самый практичный путь для нативной сборки C через GCC — использовать MSYS2 и пакет MinGW-w64 GCC.

# Открой "MSYS2 UCRT64" терминал
pacman -Suy
# если терминал закрылся после обновления — открой снова и повтори
pacman -Suy
pacman -S --needed mingw-w64-ucrt-x86_64-gcc
gcc --version

Документация по установке на Windows: GCC binaries (официальная страница GCC), MSYS2, Updating MSYS2, MinGW-w64: MSYS2 (GCC), пакет mingw-w64-ucrt-x86_64-gcc.

Первая программа на C

Создадим файл hello.c:

#include <stdio.h>

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

Компиляция и запуск:

gcc hello.c -o hello
./hello

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

Полезные флаги GCC

Базовая «рабочая» команда для C-проекта:

gcc main.c -std=c23 -Wall -Wextra -Werror -pedantic -O3 -o app

Стандарт языка

  • -std=c23 — компилировать по стандарту ISO C23.
  • Актуальные альтернативы: -std=c99, -std=c11, -std=c17.
  • Если нужен GNU-диалект с расширениями, используйте варианты вида -std=gnu11, -std=gnu17.

Документация: C Dialect Options.

Предупреждения

  • -Wall — включает большой набор базовых предупреждений, но не «все возможные».
  • -Wextra — добавляет дополнительные проверки к -Wall.
  • -Wpedantic — предупреждает о конструкциях, выходящих за рамки выбранного стандарта C.
  • -Werror — превращает предупреждения в ошибки (полезно в CI, чтобы не копить технический долг).

Документация: Warning Options.

Оптимизация

  • -O0 — без оптимизаций (по умолчанию), удобно для отладки.
  • -Og — компромисс: оптимизации, которые меньше мешают отладке.
  • -O2 — практичный стандарт для production-сборки.
  • -O3 — более агрессивные оптимизации; иногда быстрее, иногда нет, нужно измерять.
  • -Os — оптимизация под размер бинарника.

Документация: Optimize Options.

Отладка

  • -g добавляет отладочную информацию для gdb и других дебаггеров.
  • Типичный вариант для локальной разработки: -Og -g.

Документация: Debugging Options.

Сборка и линковка

  • -c — компиляция в объектный файл без линковки.
  • -o file — имя выходного файла.
  • -Ipath — путь к заголовочным файлам.
  • -Lpath и -lname — путь поиска и имя библиотеки при линковке.

Документация: Overall Options, Directory Options, Link Options.

Этапы сборки

GCC проходит несколько шагов: препроцессинг, компиляция, ассемблирование и линковка. Их можно посмотреть отдельно:

gcc -E main.c -o main.i   # препроцессор
gcc -S main.i -o main.s   # C -> ASM
gcc -c main.s -o main.o   # ASM -> object
gcc main.o -o app         # линковка

Итог

C даёт точный контроль над программой, а GCC предоставляет надёжный инструмент для сборки и отладки. Хорошая базовая привычка: компилировать с предупреждениями (-Wall -Wextra -Werror -pedantic) и исправлять их сразу.