extern "C" По умолчанию аргумент работает или нет? - PullRequest
0 голосов
/ 28 мая 2018

С Здесь кажется, что аргумент по умолчанию не поддерживается C.

У меня есть следующий метод в экспортированной библиотеке:

extern "C" 
{
    __declspec (dllexport) uintptr_t Method(int freq, int *pRetval, bool *support2MHz);
}

Если я сделал последнийнеобязательный аргумент, подобный этому:

extern "C" 
{
    __declspec (dllexport) uintptr_t Method(int freq, int *pRetval, bool *support2MHz = NULL);
}

Моя dll все еще скомпилирована. У меня вопрос, почему? Все говорят, что аргументы по умолчанию не поддерживаются в коде C.

Я использую C ++ для MS 2015.

1 Ответ

0 голосов
/ 28 мая 2018

Как уже отмечалось в комментариях molbdnilo, extern "C" не означает «это код C», но «это код со связью C» - т.е. искажение имени для этой функции не будет выполнено, поэтому вы сможетечтобы вызвать его из C с "ожидаемым" синтаксисом вызова функции.Компиляторы C ++ управляют именами функций, чтобы они могли поддерживать перегрузку функций, поскольку имена символов различных перегрузок одной и той же функции должны быть уникальными (в основном они используют область действия, имя и типы аргументов для создания уникального имени символа).

Согласно [dcl.fct.default] , параграфы 1 и 2 стандарта:

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

[Пример: объявление

void point(int = 3, int = 4);

объявляет функцию, которую можно вызывать с нулевым, одним или двумя аргументами типаint.Его можно вызывать любым из следующих способов:

point(1,2); point(1); point();

Последние два вызова эквивалентны point(1,4) и point(3,4) соответственно.- конец примера]

Кроме того, в параграфе 9 указано:

Аргумент по умолчанию не является частью типа функции.[Пример:

int f(int = 0);

void h() {
    int j = f(1);
    int k = f();                      // OK, means f(0)
}

int (*p1)(int) = &f;
int (*p2)() = &f;                   // error: type mismatch

- конец примера]

Таким образом, для функции с аргументом по умолчанию int foo(int x, int y = 0) компилятор не будет генерировать две перегрузки (int foo(int x, int y) иint foo(int x), с y, установленным на 0), но вместо этого заменяйте каждый вызов вида foo(x) на вызов foo(x, 0).В вашем конкретном примере с extern "C" это означает, что компилятор генерирует только один символ со связью C для Method, поэтому имя не конфликтует.

Такое поведение для различных компиляторов можно увидеть в живой пример на godbolt .

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

...