Включение заголовков C в пространство имен С++ - стандартное поведение?
Я считал, что файлы заголовков C должны быть включены в верхний уровень программы на С++.
Во всяком случае, я случайно обнаружил, что С++ разрешает включение заголовков C в подпространство имен.
namespace AAA {
extern "C" {
#include "sqlite3.h" // C API.
}
}
И тогда все типы и функции C будут помещены в пространство имен. Более интересно, что все связанные функции C также работают! Я также обнаружил, что это может вызвать некоторые проблемы с препроцессором, но, кроме того, кажется, что это работает очень хорошо.
Это стандартное поведение? (Я использую Clang 3.x) Если это так, то каково название этой функции и где я могу найти эту функцию, упомянутую в стандарте?
Ответы
Ответ 1
Вы можете даже делать странные вещи, такие как
//test.c
int
#include "main.h"
{
return 1;
}
//main.h
main(void)
Макросы препроцессора расширяются до того, как будет выполнена любая проверка синтаксиса. Вышеприведенный пример будет расширяться до
int
main(void)
{
return 1;
}
который является юридическим кодом. Хотя вам действительно следует избегать таких примеров, бывают случаи, когда включение в другой элемент весьма полезно. В вашем вопросе это зависит от того, как имена искажаются во время компиляции. Если все определения в файле заголовка объявлены с помощью extern "C"
, имена будут искаться в объектном файле, но это не так, если объектный файл, содержащий реализацию, не использует то же пространство имен, что и определение в коде потребления и не объявляет его extern "C"
.
Ответ 2
Это стандартное поведение?
Да - поведение поддерживается стандартом, поскольку компилятор С++ на самом деле не имеет понятия "C" в сравнении с "С++", за исключением случаев, когда extern "C"
используется для запрещения манипулирования пространства имен.
Следствием не подавления искажения является то, что вы можете столкнуться с ошибками "неразрешенных символов" в времени ссылки, если вы попытаетесь связать с библиотекой C, определяющей символы вне строки (extern
переменные, функции), упомянутые в заголовке.
Если это [стандартная функция], как называется эта функция, и где я могу найти эту функцию, указанную в стандарте?
Это просто следствие того, как работает #include
, что определено в 16.2. Включение исходного файла [cpp.include], в решающей степени:
[a #include
] вызывает замену этой директивы всем содержимым исходного файла, идентифицированного указанной последовательностью между "разделителями".
Итак, что бы ни случилось с заголовком "C", точно так же, как если бы окружающие операторы namespace
/extern
и фигурные скобки существовали в верхней и нижней части файла заголовка... к тому времени, когда следующий этап компиляция начинает бесполезно, откуда пришел исходный код (за исключением отображения сообщений об ошибках, которые правильно относятся к исходному файлу).