Есть ли способ объявить комплексное число без включения <complex.h>? - PullRequest
0 голосов
/ 17 мая 2019

Я хочу использовать библиотеку <complex.h> для ускорения некоторых вычислений, которые могут включать до 20 сложных элементов и операций (+ - * /).Однако мой коллега объявил структуру:

struct complex {
    double a;
    double b;
};

Поэтому макрос complex, поступающий из библиотеки, не может использоваться из-за конфликта с вышеуказанной структурой.

Дело в том, что яне может изменить имя структуры из-за огромного влияния на текущий проект.Вместо этого я попытался использовать макрос _Complex и удалить заголовок #include <complex.h>, это сработало, но _Imaginary_I, _Complex_I или I не работает.

#include <stdio.h>      /* Standard Library of Input and Output */
// #include <complex.h>    /* I want to remove this */    

int main() {
    struct complex
    {
        double a;
        double b;
    };
    double _Complex z1 = 1.0;// + 3.0 * _Complex_I;
    double _Complex z2 = 1.0;// - 4.0 * _Complex_I;    

    // none of these work
    double _Complex z = CMPLX(0.0, -0.0);
    double _Complex z3 = 1.0 + 1.0 * _Imaginary_I;
    double _Complex z4 = 1.0 + 1.0 * _Complex_I;
    double _Complex z5 = 1.0 + 1.0 * I;    

    printf("Starting values: Z1 = %.2f + %.2fi\n", creal(z1), cimag(z1));    

}

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

Мой __STDC_VERSION__ равен 201112L, а __VERSION__ равен "4.2.1 Совместимость Apple LLVM 10.0.1 (clang-1001.0.46.4)».

Ответы [ 3 ]

8 голосов
/ 17 мая 2019

Стандарт C предвидел эту проблему и специально для нее есть пункт 7.3.1p7 :

Несмотря на положения 7.1.3, программа может отменить определение и, возможно, затем переопределить макросы complex, imaginary и I.

Что это значит, вы можете сделать это:

#include <stdio.h>
#include <complex.h>
#undef complex     /* after including complex.h, before declaring struct complex */

//#include <header_that_defines_struct_complex.h>
struct complex
{
    double a;
    double b;
};

И теперь ваш код может без проблем использовать struct complex и double _Complex и имеет доступ к сложным математическим функциям, объявленным в <complex.h>.

int main(void)
{
    // this should all be fine now
    double _Complex z = CMPLX(0.0, -0.0);
    double _Complex z1 = 1.0 + 3.0 * _Complex_I;
    double _Complex z2 = 1.0 - 4.0 * _Complex_I;    
    double _Complex z3 = 1.0 + 1.0 * _Imaginary_I;
    double _Complex z4 = 1.0 + 1.0 * _Complex_I;
    double _Complex z5 = 1.0 + 1.0 * I;    
    printf("Starting values: Z1 = %.2f + %.2fi\n", creal(z1), cimag(z1));    

    return 0;
}

Обратите внимание, однако, что нет способа сделать struct complex автоматически конвертируемым или «совместимым с», double _Complex, даже если они, вероятно, имеют одинаковое расположение в памяти. Вам придется копировать туда-сюда вручную.

2 голосов
/ 17 мая 2019

Ваша настоящая проблема -

my colleague has declared a struct:

    struct complex {
        double a;
        double b;
    };

Исправьте это.

Все другие способы решения этой проблемы создают то, что будет де-факто недокументированной зависимостью от отмена стандартная функция C - определение макроса complex.Лучшее, что ваша организация собирается сделать, это, вероятно, что-то вроде: «На странице 4 наших стандартов кодирования [у вас есть стандарты кодирования?] Говорится, что вам нужно #undef complex после вас #include <complex.h>, а затем #include <stomps/on/complex.h> после этого".И какова вероятность того, что ваша организация так много делает?И затем удостоверится, что все в программе знают это?

Скорее всего, они не собираются прилагать усилия, чтобы сделать это, и они даже не приблизятся.

Вы попадете с небольшим количеством недокументированного племенизнание.

Опять-таки, есть ли в вашей организации письменные стандарты кодирования и применяются ли они на самом деле?Если вы не можете ответить «да» на это, вам действительно нужно устранить причину проблемы сейчас, а не оставлять ее скрытой, ожидая, что в будущем возникнут еще более серьезные проблемы.

, которые создает struct complexне только зависимость от отмены стандартной функции C, но и зависимость порядка от директив #include и оператора #undef.Нет реального способа узнать, что может произойти, если эти зависимости строго не соблюдаются - нельзя исключать странные результаты и необъяснимые неудачи в будущем.

Да, это законно, и не так сложно его определить.макрос с #undef complex.Но что происходит , когда кто-то не делает этого или делает это в неправильном порядке?

Написание и поддержка программного обеспечения достаточно сложны, когда вы делаете это правильно.Не усложняйте жизнь программы, сознательно делая что-то сомнительное в лучшем случае.

2 голосов
/ 17 мая 2019

В качестве альтернативы вы можете переопределить структурный комплекс, который определен в the_other_colleagues_header

#define complex my_complex
#include <the_other_colleagues_header>
#undef complex

#include <complex.h>

Теперь внутри вашего .c файла вы можете использовать как complex, так и my_complex, а другие все еще могут использоватьstruct complex как обычно.Или напишите обертку для complex.h и позвоните из своего приложения

Но лучшим решением было бы попросить другого коллегу изменить имя.Обычно плохая идея использовать стандартные имена

...