Где я могу найти ресурсы о "современном" программировании на C?
Несмотря на то, что он читал K & R и даже преподавал классы C, я смущающе не могу полностью понять, что можно назвать "современным".
Кажется, в современном программировании много неписаных условностей, которые, насколько я знаю, нигде не документированы.
Возьмем, к примеру, исходный код SQLite. В нем я нахожу, например:
SQLITE_API int sqlite3_close(sqlite3 *);
Что означает SQLITE_API
? Как это даже синтаксически правильно?
Или это:
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
Есть ли принятое соглашение где-нибудь, когда префикс макросов с символами подчеркивания? Иногда я вижу макросы с двумя символами подчеркивания.
Или как использовать типы фиксированного размера, такие как uint32
и т.д. Когда следует использовать эту практику, а когда нет? Как насчет типа new-ish bool
, когда он должен быть предпочтительнее простых ints?
Вот некоторые из вопросов, которые я задаю себе, когда читаю исходный код других людей. Есть ли ссылка где-нибудь, которая могла бы помочь мне ответить на эти вопросы?
Ответы
Ответ 1
SQLITE_API
в коде, подобном этому, очень вероятно, что препроцессор определяет, что беспокоится об разоблачении вызова, например. сборка библиотеки DLL. Это довольно часто.
Если все это верхний регистр в C, скорее всего, это символ препроцессора, и хорошая идея - часто запускать игру через препроцессор и читать то, что выходит.
Ответ 2
Стандарты кодирования Afaik GNU постоянно обновляются/обновляются, поэтому может быть хорошим снимком "современного" стиля.
http://www.gnu.org/prep/standards/
Re: особенно одиночные или двойные подписи, по моему опыту и тому, что я часто читаю; это было бы более безопасным, чтобы избежать двойных подчеркивающих префиксов, поскольку они обычно "зарезервированы" для элементов структуры/системы/компилятора и для компилятора, поэтому макросы, предназначенные для использования в рамках модуля/пакета/единицы/проекта, которые они определены, должны избегать вообще-то презервативом.
Большинство стимулов имеют свои собственные стандарты кодирования и руководства, которые могут значительно отличаться. Как всегда, ключевое значение имеет согласованность.
Ответ 3
Это
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
- это просто защита от множественного включения.
Он предотвращает ошибки в случае, когда xxx.h включает этот файл, а также yyy.h, а yyy.h также включает этот файл.
Ответ 4
SQLITE_API
является примером того, что я называю "идентификатор типа вызова". Это директива препроцессора, используемая для улучшения переносимости в файлах заголовков, где заголовочный файл должен определять определенный режим вызова, как правило, между основным кодом и DLL или аналогичным.
В зависимости от используемой платформы и компилятора SQLITE_API обычно расширяется до некоторой комбинации доступных соглашений вызова, таких как cdecl
, __stdcall
или аналогичных.
Вы должны найти его определение в файле заголовка.
Ответ 5
Я не думаю, что есть одна замечательная ссылка на этот материал. То, что вы наблюдаете, - это серия конвенций, некоторые из которых очень широко используются в отрасли, а некоторые, возможно, более специфичны для вашей собственной базы кода, которые возникли для обработки стандартных задач или ситуаций в крупномасштабных проектах программного обеспечения в C (и производных). Как вы заметили, K & R - отличный инструмент обучения, но не затрагивает ни одно из этих широкомасштабных соглашений о проектах, которые в основном появились органично и в промышленности.
Вы даете два замечательных примера. Во-первых, это #define
d где-то, чтобы украсить функцию, чтобы она либо экспортировалась правильно, либо просто задокументирована, что она будет экспортироваться. Второй шаблон называется " включить охрану" (см. Ссылку), а обычные подчеркивания являются необязательными, но являются хорошим способом избежать конфликта с нормальной магией -number.
Существует множество соглашений, многие из которых включают препроцессор с определениями и макросами. Лучше всего, наверное, посмотреть и спросить о каждом шаблоне индивидуально. Вы, вероятно, получите вдумчивые ответы здесь об обосновании и хорошем обсуждении.
Ответ 6
Expert C Programming Отличное продолжение работы с K & R. Не откладывайте название. Это очень доступная книга, если вы знаете основы C. Она охватывает множество ситуаций реального мира, которые K & R довольно коротки.
С учетом сказанного, на самом деле нет никакой замены для чтения и написания кода. Большинство современных конвенций не являются действительно стандартами и часто придерживаются по-разному в разных кодовых базах. Это просто общие решения проблем и ограничений, с которыми каждый сталкивается с написанием на этом языке. Самое главное, на мой взгляд, понять, что это за проблемы и ограничения.
Ответ 7
Во-первых, вы должны понимать, что определение "_SQLITE3_H_" на самом деле запрещено - все имена, начинающиеся с символа подчеркивания, за которым следуют другое подчеркивание или заглавная буква, зарезервированы. Когда вы это делаете, простой ответ заключается в том, что, вероятно, лучше избегать использования лидирующего подчеркивания во всем, что вы определяете. Оставьте их для реализации.
Что касается SQLLITE_API, он, вероятно, по-разному определяется на разных платформах. Например, если вы строили его как DLL на Windows, вероятно, было бы определено что-то вроде:
#define SQLLITE_API __declspec(dllexport) __stdcall
С другой стороны, когда вы используете заголовок в своем коде, он, вероятно, расширяется до следующего:
#define SQLLITE_API __declspec(dllimport) __stdcall
В основном они сообщают компилятору, что при создании DLL вы хотите, чтобы функция экспортировалась (поэтому она видима для остального мира). Когда вы используете его в своем собственном коде, он сообщает компилятору, что данная функция будет получена из библиотеки DLL.
Ответ 8
Я бы рекомендовал Дэвид Р. Хансон "C-интерфейсы и реализации: методы создания многоразового программного обеспечения". Я думаю, что это одна из лучших книг об использовании языка С.