Существует ли причина, что C99 не делает перегрузки функции поддержки?

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

, Если Вы не делаете репродукции, затем Вы

  • экономите время теперь, но
  • подвергаются риску

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

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

6
задан Imagist 21 August 2009 в 23:25
поделиться

3 ответа

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

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

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

В C функции становятся именами символов для компоновщика, поэтому, когда вы пишете

int main(int argc, char **argv) { return 1; }

, компилятор предоставляет архив объектного кода, который содержит объект с именем main .

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

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

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

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

Я думаю, что вряд ли C когда-либо будет реализовывать какую-либо функцию, которая создала бы код, с которым так же сложно взаимодействовать, как C ++.

Изменить : Imagist спрашивает:

Будет это действительно будет менее портативным или труднее взаимодействовать с функция, если вы разрешили int main (int argc, char ** argv) на что-то вроде main-int-int-char ** вместо main (а это было частью стандарта)? Я не вижу здесь проблемы. По факту, мне кажется, что это дает вам дополнительная информация (которая может быть использована для оптимизации и тому подобного)

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

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

C ++ делает это, кодируя всю необходимую информацию о типах в искаженных именах объектов. C, однако, имеет существенно иную направленность, стремясь стать своего рода переносимым языком ассемблера. Таким образом, C предпочитает иметь строгое соответствие между объявленным именем и именем символа результирующего объекта. Если C искалечил это ' s имен, даже стандартизованным и предсказуемым образом, вам придется приложить большие усилия, чтобы сопоставить измененные имена с желаемыми именами символов, иначе вам придется отключить его, как в С ++. Эти дополнительные усилия почти не приносят пользы, потому что в отличие от C ++ система типов C довольно мала и проста.

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

27
ответ дан 8 December 2019 в 02:05
поделиться

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

Кроме того, C не поддерживает строгую типизацию. Многие вещи неявно конвертируются друг в друга в C. Сложность правил разрешения перегрузки может внести путаницу в такой язык.

19
ответ дан 8 December 2019 в 02:05
поделиться

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

В целом, C99 задумывался как скромный пересмотр, в значительной степени совместимый с существующей практикой. Перегрузка была бы довольно серьезным отклонением.

6
ответ дан 8 December 2019 в 02:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: