Каковы наиболее распространенные соглашения об именах в C? - PullRequest
103 голосов
/ 12 ноября 2009

Какие соглашения об именах обычно используются в C? Я знаю, что есть как минимум два:

  1. GNU / linux / K & R с функцией lower_case_
  2. ? название ? с функциями UpperCaseFoo

Я говорю о Си только здесь. Большинство наших проектов - это небольшие встроенные системы, в которых мы используем C.

Вот тот, который я планирую использовать для моего следующего проекта:


Соглашение о присвоении имен C

Struct              TitleCase
Struct Members      lower_case or lowerCase

Enum                ETitleCase
Enum Members        ALL_CAPS or lowerCase

Public functions    pfx_TitleCase (pfx = two or three letter module prefix)
Private functions   TitleCase
Trivial variables   i,x,n,f etc...
Local variables     lower_case or lowerCase
Global variables    g_lowerCase or g_lower_case (searchable by g_ prefix)

Ответы [ 10 ]

106 голосов
/ 12 ноября 2009

Самое важное здесь - это последовательность. Тем не менее, я следую соглашению о кодировании GTK +, которое можно обобщить следующим образом:

  1. Все макросы и константы в шапках: MAX_BUFFER_SIZE, TRACKING_ID_PREFIX.
  2. Имена структур и typedef в верблюжьем регистре: GtkWidget, TrackingOrder.
  3. Функции, работающие со структурами: классический стиль C: gtk_widget_show(), tracking_order_process().
  4. Указатели: здесь ничего особенного: GtkWidget *foo, TrackingOrder *bar.
  5. Глобальные переменные: просто не используйте глобальные переменные. Они злые.
  6. Функции, которые есть, но не должны вызываться напрямую или иметь неясное использование или что-то еще: один или несколько подчеркивает в начале: _refrobnicate_data_tables(), _destroy_cache().
27 голосов
/ 12 ноября 2009

«Структурные указатели» не являются сущностями, которым требуется соглашение об именовании, чтобы покрыть их. Они просто struct WhatEver *. НЕ скрывайте, что указатель связан с умным и «очевидным» typedef. Он не имеет смысла, дольше печатается и разрушает баланс между объявлением и доступом.

13 голосов
/ 12 ноября 2009

Ну, во-первых, C не имеет публичных / приватных / виртуальных функций. Это C ++, и у него разные соглашения. В Си обычно есть:

  • Константы в ALL_CAPS
  • Подчеркивает, что разграничивает слова в структурах или именах функций, вряд ли вы когда-нибудь видели верблюжий случай в C;
  • структуры, typedefs, объединения, члены (объединения и структуры) и значения enum обычно в нижнем регистре (по моему опыту), а не в соглашении C ++ / Java / C # / etc, согласно которому первая буква должна быть заглавной, однако это возможно и в Си.

C ++ более сложный. Я видел настоящую смесь здесь. Случай верблюда для имен классов или нижнего регистра + подчеркивания (случай верблюда более распространен в моем опыте). Структуры используются редко (и, как правило, потому что библиотека требует их, в противном случае вы будете использовать классы).

9 голосов
/ 08 января 2015

Кодируя C #, Java, C, C ++ и цель C одновременно, я принял очень простое и понятное соглашение об именах, чтобы упростить мою жизнь.

Прежде всего, он опирается на мощь современных IDE (таких как eclipse, Xcode ...), с возможностью быстрого получения информации при наведении курсора или нажатии Ctrl ... Принимая это, я исключил использование любого префикса, суффикса и других маркеров, которые просто задаются в среде IDE.

Тогда соглашение:

  • Любые имена ДОЛЖНЫ быть читаемым предложением, объясняющим, что у вас есть. Как "это мое соглашение".
  • Затем, 4 способа получить соглашение из предложения:
    1. THIS_IS_MY_CONVENTION для макросов, перечислимых элементов
    2. ThisIsMyConvention для имени файла, имени объекта (класс, структура, перечисление, объединение ...), имени функции, имени метода, typedef
    3. this_is_my_convention глобальные и локальные переменные,
      параметры, элементы структуры и объединения
    4. thisismyconvention [необязательно] очень локальные и временные переменные (такие как индекс цикла for ())

И это все.

Даёт

class MyClass {
    enum TheEnumeration {
        FIRST_ELEMENT,
        SECOND_ELEMENT,
    }

    int class_variable;

    int MyMethod(int first_param, int second_parameter) {
        int local_variable;
        TheEnumeration local_enum;
        for(int myindex=0, myindex<class_variable, myindex++) {
             localEnum = FIRST_ELEMENT;
        }
    }
}
8 голосов
/ 12 ноября 2009

Я бы рекомендовал не смешивать регистр верблюдов и подчеркивание (как вы предлагали для членов структуры). Это смущает. Можно подумать, эй, у меня есть get_length, поэтому, вероятно, у меня должно быть make_subset, а потом вы узнаете, что на самом деле makeSubset Используйте принцип наименьшего удивления и будьте последовательны.

Я считаю, что CamelCase полезен для ввода имен, таких как struct, typedefs и enums. Это все, хотя. Для всего остального (имена функций, имена членов структуры и т. Д.) Я использую underscore_separation.

7 голосов
/ 24 января 2018

Знаешь, мне нравится, чтобы все было просто, но понятно ... Вот что я использую в C:

  • Тривиальные переменные : i,n,c и т. Д. (Только одна буква. Если одна буква не очистить, а затем сделать его локальной переменной)
  • Локальные переменные : lowerCamelCase
  • Глобальные переменные : g_lowerCamelCase
  • Постоянные переменные : ALL_CAPS
  • Переменные указателя : добавить p_ к префиксу. Для глобальных переменных это будет gp_var, для локальных переменных p_var, для константных переменных p_VAR. Если используются дальние указатели, используйте fp_ вместо p_.
  • Структуры : ModuleCamelCase (Модуль = полное имя модуля или 2-3-буквенное сокращение, но все еще в CamelCase.)
  • Переменные элемента структуры : lowerCamelCase
  • Перечисления : ModuleCamelCase
  • Enum Values ​​: ALL_CAPS
  • Публичные функции : ModuleCamelCase
  • Частные функции : CamelCase
  • Макросы : CamelCase

Я набираю определения своих структур, но использую то же имя для и тег, и определение типа. Тег не предназначен для общего использования. Вместо этого предпочтительнее использовать typedef. Я также пересылаю объявление typedef в открытый заголовок модуля для инкапсуляции и, таким образом, могу использовать имя typedef в определении.

Полный struct Пример :

typdef struct TheName TheName;
struct TheName{
    int var;
    TheName *p_link;
};
6 голосов
/ 13 ноября 2009

Вот (по-видимому) необычный, который я нашел полезным: имя модуля в CamelCase, затем подчеркивание, затем имя функции или области действия файла в CamelCase. Так, например:

Bluetooth_Init()
CommsHub_Update()
Serial_TxBuffer[]
3 голосов
/ 12 ноября 2009

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

О единственном предложении, которое я добавил бы, я полюбил _t в конце типов в стиле uint32_t и size_t. Это очень странно для меня, хотя некоторые могут жаловаться, что это просто "обратный" венгерский.

0 голосов
/ 27 сентября 2017

Может быть много, в основном IDE диктуют некоторые тенденции, и соглашения C ++ также продвигаются. Для C обычно:

  • UNDERSCORED_UPPER_CASE (определения макросов, константы, члены перечисления)
  • underscored_lower_case (переменные, функции)
  • CamelCase (пользовательские типы: структуры, перечисления, объединения)
  • uncappedCamelCase (в стиле Java)
  • UnderScored_CamelCase (переменные, функции в виде пространств имен)

Венгерские обозначения для глобалов хороши, но не для типов. И даже для тривиальных имен используйте как минимум два символа.

0 голосов
/ 06 августа 2017

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

Хорошая практика: имя библиотеки + имя модуля + действие + тема

Если деталь не релевантна, просто пропустите ее, но всегда следует указывать хотя бы имя модуля и действие.

Примеры:

  • имя функции: os_task_set_prio, list_get_size, avg_get
  • определение (здесь обычно нет действие часть): OS_TASK_PRIO_MAX
...