Включить .c вместо заголовка (.h) - MISRA C

Является ли использование #include «component.c» плохой практикой или есть какое-либо нарушение стандартных правил мисры? (потенциально правило 3-3-1)

До сих пор я понимаю, что это обычно классифицируется как плохая практика, но может использоваться в определенных сценариях, будет ли это особой проблемой для приложений, критически важных с точки зрения безопасности?

Правило Misra 3-3-1 гласит, что объекты или функции с внешней связью должны быть объявлены в заголовочном файле.

Да, это наихудшая практика, и она, по крайней мере, приведет к ошибкам компоновщика.

πάντα ῥεῖ 31.03.2023 17:24

Как правило, это плохая практика для всего программирования на C, а не только для MISRA. Вы используете компоновку, чтобы объединить результат компиляции отдельных файлов C.

Barmar 31.03.2023 17:24

Я не знаю, как эта практика может повысить какую-либо безопасность. Не делай этого.

Jabberwocky 31.03.2023 17:40

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

nielsen 31.03.2023 18:45

MISRA C 3-3-1 не существует. Вы используете C или C++? Вам нужно знать, на каком языке программирования вы программируете, прежде чем приступать к более сложным вещам, таким как соответствие требованиям MISRA.

Lundin 03.04.2023 08:15

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

Lundin 03.04.2023 08:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
176
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Ответ принят как подходящий

Когда вы пишете такую ​​программу, это называется единство сборки . Хороший пример такой программы — компилятор для языка программирования Odin. Так что это можно сделать, но, как и все остальное, есть компромиссы.

плюсы

  • Он помещает больше источника в одну единицу перевода. Это может помочь в оптимизации, аналогично тому, как работает оптимизация времени компоновки, поскольку компилятор может фактически видеть исходный код из функций в других файлах C.

  • Меньше беспорядка в файлах проекта (меньше заголовков) и, следовательно, меньше повторений.

  • Сильно упрощенная сборка; Это может быть так же просто, как создать только один файл, даже если в проекте много файлов.

минусы

  • Труднее понять коллегам, которые используют более распространенные методы.

  • Вы больше не можете определить статическую переменную с очень общим именем в файле C, потому что этот файл C может быть частью более крупной единицы перевода. Вы получите более подробные имена переменных.

  • Как правило, это замедляет сборку. Системы сборки (такие как make) могут ускорить компиляцию, только перекомпилируя то, что зависит от всех изменений. Если вы объединяете вещи в единую единицу перевода, все это нужно будет создавать для каждого изменения. В большом проекте это приведет к большему потреблению памяти во время сборки.

  • Вы не можете распараллелить сборку.

Нарушает ли это MIRSA?

Я на самом деле не знаю, но это не нарушает правило, которое вы опубликовали:

Правило Misra 3-3-1 гласит, что объекты или функции с внешней связью должны быть объявлены в заголовочном файле.

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

Я никогда раньше не слышал термина «сборка единства». Я думаю, вы узнаете что-то новое каждый день. Однако, судя по описанию в Википедии, сборка единства — это конкретный вариант использования файлов .c, а не термин, описывающий практику в целом. В таком случае я не думаю, что будет правильно говорить: «Когда вы пишете такую ​​программу, это называется сборкой единства».

John Bollinger 31.03.2023 17:55

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

HolyBlackCat 31.03.2023 18:04

Это также вопрос безопасности с точки зрения того, что вы можете не захотеть предоставлять свой код, поэтому вы просто предоставляете заголовок и объектные файлы.

Не знаете, как это решает вопрос о #include-ing файле C?

Andrew 02.04.2023 11:33

если вы #include .c файл, он вам нужен, поэтому вам нужен код, но если вы #include .h файл, вам просто нужно иметь заголовочный файл и объектный файл, чтобы дать его для ссылки.

Dimitris Gavriil 02.04.2023 12:33

Вы ссылаетесь на стандарт MISRA C++, а не на стандарт MISRA C. Стандартное правило MISRA C++ 3-1-1 не запрещает вам #include-ing C-файлы в другие C-файлы, потому что любой C-файл может включать один другой и ничего не объявлять как имеющее внешнюю связь. Правило/требование относится к внешней компоновке, а не к включению C-файла. Я полагаю, что если бы они добавили правило для включения других файлов C, оно было бы в разделе «Включение исходного файла» правил 16-2-X, но я только что проверил, и ничего не говорится о включении других файлов C. Лично я не возражаю против включения других файлов C, потому что я вижу #include просто как операции копирования и вставки, которые можно использовать по своему усмотрению.

Использование #include "component.c" считается плохой практикой

Вообще говоря, да.

Обычно функция включения файлов препроцессора зарезервирована для поддержки факторизации общих объявлений в их собственных файлах, чтобы их не нужно было дублировать в нескольких источниках. Такой факторинг дает огромные преимущества для удобства сопровождения во всех проектах, кроме самых маленьких, и это почти требование, чтобы библиотеки можно было использовать. Файл, содержащий только такие объявления, обычно называется «заголовком» и обычно именуется с суффиксом .h. В этом смысле проблема частично заключается в именовании файлов и шаблонах программирования.

С другой стороны, исходные файлы C, содержащие определения функций или объектов (в отличие от объявлений), обычно именуются с суффиксом .c. Язык C запрещает несколько внешних определений одного и того же идентификатора (функции или имени переменной) в одной и той же программе, поэтому такие .c файлы не могут быть #include преобразованы более чем в одну единицу перевода, участвующую в программе, и если они включены хотя бы в одну, то они также не должны компилироваться напрямую. Обычный способ создать программу из нескольких файлов .c — это скомпилировать их независимо, а затем связать вместе.

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

Есть ли какое-либо нарушение стандартных правил мисры? (потенциально правило 3-3-1)

По сути, это не нарушает правило MISRA 3-3-1, но упрощает написание кода, нарушающего это правило. То есть сделать возможным иметь все необходимые внешние объявления в одном файле .c плюс его включения вместо предоставления отдельного заголовка.

Я не вижу другого правила MISRA-2012, которое нарушило бы такое включение. Но это не выдерживает никакой критики со мной в код-ревью.

Правило 3-1-1 — это правило MISRA C++:2008.

Применимыми рекомендациями MISRA C:2012 являются (вероятно) правила 20.2 и 20.3, которые не запрещают использование расширений .c.

--

В MISRA C:2004 Правило 8.5 запрещало исходный код в заголовочном файле (предполагаемом, что это файл .h). Это правило было удалено для MISRA C: 2012, чтобы разрешить использование функций inline.

--

Лично я считаю, что #include-инг .c-файла — плохая идея — это предполагает неправильное понимание языка, компилятора и компоновщика.

Если вы сделаете это, расширенный файл будет считаться одной единицей перевода для целей анализа...

(см. профиль для принадлежности)

Другие вопросы по теме