- Что я должен включить в программы на С++,
stdio.h
илиcstdio
? и почему? - Почему два файла заголовка предоставляют одну и ту же функциональность?
- Что говорит об этом стандарт?
- Как мне включить другие такие заголовки, есть ли базовое правило, которому я должен следовать?
Должен ли я включать <xxxx.h> или <cxxxx> в программы на С++?
Ответ 1
Рассмотрим следующие программы:
#include<stdio.h>
int main()
{
printf("Hello World");
return 0;
}
#include<cstdio>
int main()
{
printf("Hello World");
return 0;
}
Оба работают так, как ожидалось. Итак, какое использование более подходит? Ответ: Ничего! Удивлен? Читай дальше.
Стандартная библиотека С++ предоставляет все стандартные заголовки C для обеспечения совместимости, в то время как язык С++ также предоставляет все эквивалентные заголовки. Как соглашение,
- Нет стандартных заголовков библиотек С++ (кроме них, для совместимости с C), есть расширения файлов и
- Все С++-эквиваленты заголовков C начинаются с
cxxxxx
.
Стандарт С++ упоминает это в Приложении D (нормативный). Особенности совместимости:
В § 2 упоминается важная отличительная точка. Это правило применяется к приведенным выше примерам:
- Включение cstdio импортирует имена символов в пространстве имен std и возможно в глобальном пространстве имен.
- Включение stdio.h импортирует имена символов в глобальном пространстве имен и возможно в пространстве имен std.
Давайте применим это правило к нашим образцовым кодам и оценим плюсы и минусы:
Пример 1: Это приводит ко всем символам из stdio.h в глобальном пространстве имен. Преимущество состоит в том, что вы можете использовать символы без какой-либо квалификации, так как они импортируются в глобальное пространство имен. Недостатком является то, что вы в конечном итоге загрязняете глобальное пространство имен многими именами символов, которые вы, вероятно, никогда не будете использовать. Это может привести к столкновению имен символов. В С++ всегда рассматривайте глобальное пространство имен как минное поле и избегайте его как можно больше.
Пример 2: Это очень плохая практика, потому что нет никакой гарантии, что реализация поместит символы в глобальное пространство имен, стандарт просто не требует этого. Мы просто полагаемся на поведение одной конкретной реализации компилятора. Мы не можем и не должны предполагать, что все компиляторы сделают это. Таким образом, строго говоря, программа не является стандартным, и это использование не переносимо во всех реализациях.
Итак, каково правильное использование?
Правильное использование - использовать cstdio
и полностью квалифицировать имена символов, а также приводить их в область с using
declarations. Это гарантирует, что все используемые символы присутствуют в пространстве имен std
, и мы не загрязняем глобальное пространство имен. Пример правильного использования:
#include<cstdio>
using std::printf;
int main()
{
printf("Hello World");
return 0;
}
Обратите внимание, что директива using namespace std;
, особенно в заголовке, не является хорошим вариантом, и вы всегда должны использовать объявления using
.
Обратите внимание, что мы рассматриваем stdio.h
vs. cstdio
здесь только пример использования, на практике он применим к all заголовкам cxxxx
и xxxx.h
, за исключением нескольких, таких как <math.h>
и <cmath>
.
Ответ 2
Поскольку этот пост немного устарел, я хотел бы поделиться следующим:
Глядя на код:
Using X.h // Compatible with C language standard
---------------
#include <X.h>
int main() {
// Invoke X corresponding function
return 0;
}
Using X // Not compatible with C language standard
--------------
#include <X>
int main() {
// Invoke X corresponding function
return 0;
}
Они компилируются и выполняются нормально!
Какой из них лучше в С++?
Относительно С++ 11 и С++ 17 спецификации:
C.5.1 (раздел из документа С++ 17)
Модификации заголовков [diff.mods.to.headers]
Для совместимости со стандартной библиотекой C стандартная библиотека С++ предоставляет заголовки C, перечисленные в D.5, но их использование устарел на С++.
Нет заголовков С++ для заголовков C
<stdatomic.h>
,<stdnoreturn.h>
и<threads.h>
, а также не являются заголовками C часть С++.Заголовки С++
<ccomplex>
(D.4.1) и<ctgmath>
(D.4.4), а также их соответствующие заголовки C<complex.h>
и<tgmath.h>
, не содержат любое содержимое из стандартной библиотеки C и вместо этого просто включите другие заголовки из стандартной библиотеки С++.
Г .5 стандартные заголовки библиотеки [des.c.headers]1. Для совместимости со стандартной библиотекой C стандартная библиотека С++ предоставляет заголовки C, показанные в таблице 141.
Оба документа С++ 11 и С++ 17 заявляют, что использование <X.h>
остается совместимым со стандартом C, хотя их использование рассматривается как устарел.
Относительно стандартное предложение С++ 20
Они анализируют "неопубликование" использование заголовков библиотеки C в С++ 20. <X.h>
отображаются зеленым цветом. Отказ С++ 11 и С++ 17 на данный момент указан как "слабая рекомендация" и "настройка" для хранения " C стандартных заголовков библиотек (c.headers )":
"Основные заголовки библиотеки C - важная функция совместимости, и в ближайшее время они не собираются никуда". (из С++ 20 review документ)
Стандарт D.5 C
заголовки библиотек [des.c.headers]Слабая рекомендация: В дополнение к вышесказанному, также удалите соответствующие C заголовки из стандарта С++, так как у нас нет соответствующие
<stdatomic.h>
,<stdnoreturn.h>
или<threads.h>
, заголовки. Как и выше, но со следующими настройками: 20.5.5.2.1 C стандартные заголовки библиотек [c.headers]Для совместимости со стандартной библиотекой C стандарт С++ библиотека предоставляет заголовки C, показанные в таблице 141. Таблица 141 - C заголовки
<assert.h> <inttypes.h> <signal.h> <stdio.h> <wchar.h>
<complex.h> <iso646.h> <stdalign.h> <stdlib.h> <wctype.h>
<ctype.h> <limits.h> <stdarg.h> <string.h>
<errno.h> <locale.h> <stdbool.h> <tgmath.h>
<fenv.h> <math.h> <stddef.h> <time.h>
<float.h> <setjmp.h> <stdint.h> <uchar.h>
Заголовок
<complex.h>
ведет себя так, как будто он просто включает заголовок. Заголовок<tgmath.h>
ведет себя так, как будто он просто включает заголовки<complex>
и<cmath>
.
Bjarne Stroustrup рекомендует максимизировать межоперативность между языки C и С++, уменьшают несовместимость столько, сколько возможное. Другие утверждают иначе, поскольку это усложняет ситуацию.
Итак, кажется, что <X.h>
не никуда не годится. В конечном счете, вы можете использовать оба. Лично я бы принял решение о том, какой из них я бы использовал, чтобы ваш код был обратно совместим с кодом C или нет.