Skip to content

Latest commit

 

History

History
184 lines (155 loc) · 11.1 KB

с_style.md

File metadata and controls

184 lines (155 loc) · 11.1 KB

C style guide

Оформление

  1. Отступ - 2 или 4 пробела (используйте одинаковую ширину отступов во всей программе). Символы табуляции использовать для отступов запрещено.

  2. Отступами выделяются: тела функций, структур/классов, вложенных блоков.

  3. Бинарные операторы отбиваются пробелами с двух сторон, после унарных пробелы не ставятся: a += b + -c.

  4. Пробелы после открывающей скобки и перед закрывающей скобкой не ставятся: f(1, (2 + 3)). Закрывающая скобка должна идти на той же строке, что и последнее выражение.

  5. Максимальная длина строки - 120 символов.

  6. Перед ; пробел не ставится. После ; в for ставится пробел.

  7. Пустые блоки записываются как {} (а не ;).

  8. Открывающая { пишется на той же строке, что и начало блока (if, while, for, объявление функции).

  9. else пишется на той же строке, что и закрывающая } от if:

    if (...) {
        ...
    } else {
        ...
    }
  10. Однострочные комментарии отделяются от кода двумя пробелами и начинаются с пробела.

  11. Пробелы в конце строки запрещены.

  12. Файл должен заканчиваться переводом строки.

  13. Перед объявлением функции/структуры/класса пустая строка обязательна.

  14. Секции #include и using должны быть упорядочены по алфавиту:

    // плохо
    #include <stdio.h>
    #include <math.h>
    // хорошо
    #include <math.h>
    #include <stdio.h>
  15. Каждая переменная объявляется на собственной строке:

    int a = 1, b = 2;  // плохо
    
    int a = 1;  // хорошо
    int b = 2;
  16. Магические константы:

// Плохо!
for (size_t i = 0; i < 100; ++i)
    for (size_t j = 0; j < 15; ++j)
        ...
        
// Хорошо!
size_t size_of_DataArray = 100; 
size_t size_of_QArray = 15; 
for (size_t i = 0; i < size_of_DataArray; ++i)
    for (size_t j = 0; j < size_of_QArray; ++j)
        ...

Именование

Правила наименования одни из самых важных, т. к. они помогают сразу определить какую сущность они определяют: тип, переменная, функция, константа, без необходимости поиска определения сущности. Также хорошие имена дают подсказки о работе вашего кода без необходимости каждый раз писать поясняющий комментарий.

В первую очередь вы должны повышать удобство "читателей" вашего кода, а не "писателей", т. к. зачастую код пишется один раз и переиспользуется или модифицируется много раз разными людьми. И как правило С/С++ разработчикам в настоящих проектах в основном приходится читать очень много кода, из-за чего следование правилам оформления повышает эффективность всех.

Используйте имена, которые описывают цель или сущность объекта. Не экономьте много символов на имена. Намного важнее, чтобы код был очевиден новым читателям с первого прочтения. Не используйте аббревиатуры, которые известны только вам. Не испульзуйте аббревиатуры, сделанные удалением символов из слов. Как правило, аббревиатура допустима, если она общеизвестна (DFS, BFS, HTTP, TCP, JSON, XML, RPC). Однобуквенные имена могут быть использованы в коротких очевидных функциях, например из 5 строк. Примеры:

  • Имя n для размера массива
  • Имя i, j, k для счетчиков цикла
  1. Имена переменных и полей структуры пишутся в нижнем регистре, слова разделяются символом подчеркивания:

    int TableName;   // плохо
    int table_name;  // хорошо
    
    int array[10];  // плохо
    int scores[10];  // хорошо
  2. Не используйте транслит в именах:

    size_t dlina_massiva;  // плохо
    size_t length;  // хорошо
  3. Для переменных-счётчиков не следует использовать имена document_number, number_document, documents_count, documents_number, count_document из-за неграмотности и неоднозначности. Для числа элементов (скажем документов) можно использовать number_documents или document_count. Для функции, долго и явно подсчитывающей это число, подойдет CountDocuments().

  4. Переменные, определенные с ключевым словом const, и чье значение определенно на все протяжение работы программы, пишутся с большими буквами, слова разделяются символом подчеркивания.

    const int MAX_SIZE = 100'000;
    const int MODULO   = 1'000'000'000 + 7;
  5. Имена типов начинаются с большой буквы, каждое слово пишется слитно и с большой буквы: MyStruct.
    Под именами типов имеются ввиду следующие сущности: структуры, enum, typedef. Пример:

    struct UrlTableProperties { ...
    
    typedef size_t Size;
    
    enum UrlTableError { ...
  6. По умолчанию, имена функций начинаются с большой буквы, каждое слово начинается с большой буквы. Имя функции должно отражать действия или задачу, которую функция делает и решает соответственно.

    AddTableEntry()
    DeleteUrl()
    OpenFileOrDie()

    Функциям, которые возвращают bool, лучше давать имена, начинающиеся на Is или Has.

    // плохо
    bool graph_connected() { ... }
    
    // хорошо
    bool IsConnectedGraph() { ... }
    
    // плохо
    bool element(int n) { ... }
    
    // хорошо
    bool HasElement(int n) { ... }

Функции

Функции нужны

  • для избежания дублирования кода;
  • для того, чтобы можно было их переиспользовать много раз в различных проектах.
  1. Порядок аргументов функции: сначала входные параметры (по значению либо по указателю), затем выходные (по указателю или значению).
  2. Передавайте аргументы в функции по константному указателю везде, где это уместно:
    // плохо
    void PrintVector(struct vector v) {
        ...
    }
    // хорошо
    void PrintVector(const struct vector* v) {
        ...
    }
  3. Не создавайте функции с избыточным числом аргументов.

Прочее

  1. Необходимо явно подключать заголовочные файлы, в которых объявляются используемые функции, структуры и т. д. Запрещено явно подключать один и тот же заголовочный файл дважды.

  2. В качестве логических операторов следует использовать &&, || и т. д.

  3. При объявлении переменной спецификаторы static/extern/... идут перед именем типа.

  4. Везде, где это возможно, используйте префиксный инкремент и декремент:

    // плохо
    i++;
    it--;
    // хорошо
    ++i;
    --it;
  5. Пишите код так, чтобы не было предупреждений (warnings) компилятора. Это нужно по двум причинам: - Обычно компилятор выдаёт предупреждения по делу, на те места, где скрыта потенциальная ошибка. - Если игнорировать "неважные" предупреждения, их может много накопиться и вы не заметите действительно важных. В частности, избегайте сравнений знаковых (int) и беззнаковых (size_t) переменных.

    // плохо
    for (int i = 0; i < v.size(); ++i) {
        ...
    }
    // хорошо
    for (size_t i = 0; i < v.size(); ++i) {
        ...
    }

Важно

Действия пользователей не могут рассматриваться в качестве причины сбоев. Все пользователи, кроме сертифицированных, специально обученных специалистов, могут делать с софтом все что заблагорассудится. Мы должны ожидать от них любого поведения. Если какие-то действия пользователей приводят к сбою, налицо недоработка в софте.

Запрещена чёрная магия!

Мы живём во времена инквизиции, дорогие друзья. Код должен быть понятен мне и вашим коллегам.