Домашнее задание касается использования макроса

#c

Вопрос:

Эти вопросы касаются моей домашней работы.
Эту тему нужно использовать, как:

 #define GENERIC_MAX(type)
type type##_max(type x, type y)
{
    return x > y ? x : y;
}
 

Суть вопроса в том, чтобы заставить этот код работать нормально:

 #include <stdio.h>

GenerateShowValueFunc(double)
GenerateShowValueFunc(int)

int main()
{

    double i = 5.2;
    int j = 3;

    showValue_double(i);
    showValue_int(j);

}
 

Результат операции выглядит следующим образом:

 i=5.2000
j=3
 

И этот код-мой текущий прогресс, но есть проблемы:

 #include <stdio.h>

#define printname(n) printf(#n);

#define GenerateShowValueFunc(type)
type showValue_##type(type x)
{
    printname(x);
    printf("=%dn", x);
    return 0;
}

GenerateShowValueFunc(double)
GenerateShowValueFunc(int)

int main()
{

    double i = 5.2;
    int j = 3;

    showValue_double(i);
    showValue_int(j);

}
 

Я не знаю, как изменить вывод с помощью типа, и я не знаю, как отобразить имя переменной. ОАО


Это оригинальное описание задачи: Пожалуйста, обратитесь к ShowValue.c ниже:

 #include <stdio.h>

GenerateShowValueFunc(double)
GenerateShowValueFunc(int)

int main()
{

    double i = 5.2;
    int j = 3;

    showValue_double(i);
    showValue_int(j);

}
 

С помощью [GenerateShowValueFunc(double)] и [GenerateShowValueFunc(int)] эти две строки вызова макросов могут помочь нам сгенерировать функции [showValue_double( double )] и [showValue_int( int )], а также в вызываемой функции main (). Результат выполнения этой программы выглядит следующим образом:

 i=5.2000
j=3
 

Пожалуйста, вставьте код, определяющий макрос GenerateShowValueFunc, в соответствующее место в программе ShowValue.c, чтобы эта программа могла скомпилироваться и работать бесперебойно.

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

1. Язык C не обеспечивает поддержку, которая облегчает работу с типами в общем виде. Это не очень хорошее домашнее задание для вводного курса C. Как называется этот курс? Вы можете создать некоторый код с гибким типом, используя _Generic . Если это так, то курс должен был рассказать об _Generic этом ; от вас не ожидали бы, что вам придется открывать его для выполнения задания.

2. Возможно, домашнее задание состоит в том , чтобы просто создать GENERIC_MAX макрос , и вы должны продемонстрировать и протестировать этот макрос, используя определенный отдельный код для int , а double не написав общий код для демонстрации и тестирования?

3. Возможно, вам понадобится еще один макрос, который принимает имя переменной для отображения и использует его с оператором строковой обработки.

4. Это неразумное использование макроса IMO. Почему они учат этому, когда ни один профессиональный разработчик не счел бы это каким-либо образом «нормальным».

5. @ОАО «Армали»

Ответ №1:

Быстрым и грязным решением было бы:

 type showValue_##type(type x)
{
    const char* double_fmt = "=%fn";
    const char* int_fmt = "=%dn";
    printname(x);
    printf(type##_fmt, x);
    return 0;
}
 

Компилятор оптимизирует переменную, которая не используется, поэтому это не повлияет на производительность. Но это может привести к предупреждениям «переменная не используется». Вы можете добавить операторы null, например (void)double_fmt; , чтобы заставить его замолчать.


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

 #include <stdio.h>

void double_show (double d)
{
  printf("%fn", d);
}

void int_show (int i)
{
  printf("%dn", i);
}

#define show(x) _Generic((x),
  double: double_show,       
  int:    int_show) (x) // the x here is the parameter passed to the function

int main()
{
  double i = 5.2;
  int j = 3;

  show(i);
  show(j);
}
 

При этом используется современное стандартное ключевое слово C11/C17 _Generic , которое может проверять типы во время компиляции. Макрос выбирает соответствующую функцию для вызова, и она типобезопасна. Вызывающему абоненту не нужно беспокоиться о том, какую функцию «показать» вызывать, и о том, что они передают правильный тип.

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

1. Я думаю, что реализация макроса для охвата GenerateShowValueFunc(double) и GenerateShowValueFunc(int) является важной частью задания. Но это может быть только мое чтение.

2. В противном случае это решение произвело на меня впечатление функцией, о которой я раньше не знал.

Ответ №2:

Без изменения показанного C-кода (т. Е. Только выполнение макросов), что я считаю обязательным требованием, следующий код имеет требуемый вывод:

 #include <stdio.h>

#define showValue_double(input) 
showValueFunc_double(#input"=%.4fn" , input)

#define showValue_int(input) 
showValueFunc_int(#input"=%dn" , input)



#define GenerateShowValueFunc(type) 
void showValueFunc_##type(const char format[], type input)
{
    printf(format, input); 
}

/* ... macro magic above;      */
/* unchangeable code below ... */

GenerateShowValueFunc(double)
GenerateShowValueFunc(int)

int main()
{

    double i = 5.2;
    int j = 3;

    showValue_double(i);
    showValue_int(j);

}
 

Выход:

 i=5.2000
j=3
 

Обратите внимание, что я создал что-то вроде таблицы поиска для спецификаторов формата для конкретного типа. Т. Е. для каждого типа, который будет поддерживаться, вам нужно добавить макрос #define showValue_ ... . Это также необходимо для ввода имени переменной в выходные данные.

При этом используется тот факт, что две «строки» объединяются компиляторами C, т. Е. "A""B" Это то же самое, что "AB" . Где "A" находится результат #input .
Остальное, т. е. требуемое определение функции, очень похоже на пример, приведенный учителем, с использованием ## оператора.

Обратите внимание, это в том случае, если имя переменной должно быть правильно указано в выходных данных.
Без i = этого было бы проще и элегантнее использовать сгенерированные функции БЕЗ showValue_double(i); явных макросов. Т. е. сгенерированные функции составляют 1:1, из чего вызываются main() . Я думаю, что это может быть то, о чем на самом деле спрашивают. Дайте мне знать, если вам нужна эта версия.

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

1. Я сделал что-то похожее на ваше #define printname(n) printf(#n); , но использование printf внутри на самом деле не работает…

2. Я пробовал это много раз, и это не сработало.

3. Я думаю, что ваш ответ ближе всего к вопросу.

4. Я тоже так думаю (неудивительно…). Но для обучения за пределами задания я рекомендую также изучить другие ответы.