Доступ к одному и тому же макросу на C из разных файлов, представляющих разные значения

#c #file #macros #header #embedded

#c #файл #макросы #заголовок #встроенный

Вопрос:

У меня есть два разных файла заголовков с одинаковыми макросами в обоих, представляющих некоторые уравнения. Например; У меня есть F1 в function1.h, а также в function2.h, но оба они представляют два разных уравнения. В некоторых случаях мне нужно будет использовать F1 из function1.h, в то время как в каком-то другом случае мне понадобится F1 из function2.h. Как я мог бы реализовать эту логику в C.

 //function1.h
#define F1 x 10
#define F2 x*10
//function2.h
#define F1 x 210
#define F2 x*99

//main.c
#include "function1.h"
#include "function2.h"

int x = 10;

if(..something..)
return(F1)       //from function1.h
if(..something..else..)
return(F1)       //from function2.h
  

// в любом случае, чтобы реализовать эту логику без двусмысленности

Комментарии:

1. Это похоже на проблему XY .

2. Вам нужно будет использовать разные метки, если вы хотите это сделать. Или вы могли бы добавить аргумент: #define F1(A) x A. Для использования в случае 1: F1 (10) и во втором случае: F1 (210). Тогда вам нужно только одно определение F1. То же самое для F2.

3. @MichaelWalz пожалуйста, проверьте обновление

4. Мне этот подход кажется совершенно неправильным. Чего вы на самом деле пытаетесь достичь? Пожалуйста, прочитайте о проблеме XY .

5. Как правило: используйте функции вместо макросов, и все ваши проблемы исчезнут.

Ответ №1:

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

Помните, что прекомпилятор просто заменяет метку макроса кодом, который «псевдонимируется» меткой макроса. Затем компилируется исходный код. Вы, вероятно, знаете это, но некоторые люди считают, что макросы — это некоторая номенклатура функций.

 #define F1 x 10
#define F2 x*10
//function2.h
#define F1 x 210
#define F2 x*99
  

Изменить на:

 #define F1(A) x A
#define F2(A) x*A
  

Вам не нужны два разных макроса в каждом случае. Вы не должны делать то, что делаете в данный момент — см. Предыдущий абзац.

Для использования:

 return(F1(10));
  

или

 return(F1(210));
  

В зависимости от случая.

Комментарии:

1. спасибо. но сценарий немного отличается. заголовочные файлы представляют собой своего рода стандарт, представляющий некоторые сложные уравнения. и косяк не может быть затронут.

2. @Mahi вы должны включить эту информацию в свой вопрос.

3. @MichaelWalz Спасибо Майклу за вашу помощь! Действительно ценю это.! «хлопает»

4. @Mahi если у вас есть два макроса с одинаковой меткой (именем) в двух разных файлах заголовков, вы не можете включить эти файлы заголовков и ожидать, что прекомпилятор предоставит им какую-то особую обработку. Вам придется переименовать один набор, если вы собираетесь использовать оба файла заголовков в одном исходном файле. То, что вы запрашиваете, не может быть выполнено без изменения имени по крайней мере двух макросов в одном из заголовочных файлов или переопределения макроса. Обойти эту проблему так, как вы ее представили, невозможно. Я не могу придумать здесь какую-либо комбинацию #ifndef и #define, которая заставит все работать так, как вам хотелось бы.

Ответ №2:

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

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

Этот код будет выглядеть следующим образом

 #include "function1.h"
int my_function1_f1(int x)
{
    return F1(x);
}
#undef F1
// You would probably have to undefine a lot more here

#include "function2.h"
int my_function2_f1(int x)
{
    return F1(x);
}
#undef F2 // Do this for neatness
  

Затем вы можете вызвать «правильную» версию F1, используя либо my_function1_f1(), либо my_function2_f1() .

Лучшим ответом было бы создать дополнительные исходные файлы, один для доступа к функциям в function1.h, а другой для доступа к функциям из function2.h .

При этом вы можете с радостью включить оба ваших новых заголовка, поскольку конфликтующая функция function1.h будет включена только в myfunction1.c, а функция function2.h будет включена только в myfunction2.c .