Подтвердить что ты не робот

Включение заголовков C в пространство имен С++ - стандартное поведение?

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

namespace AAA {
    extern "C" {
        #include "sqlite3.h"     // C API.
    }
}

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

Это стандартное поведение? (Я использую Clang 3.x) Если это так, то каково название этой функции и где я могу найти эту функцию, упомянутую в стандарте?

4b9b3361

Ответ 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 и фигурные скобки существовали в верхней и нижней части файла заголовка... к тому времени, когда следующий этап компиляция начинает бесполезно, откуда пришел исходный код (за исключением отображения сообщений об ошибках, которые правильно относятся к исходному файлу).