Scott Wang
Scott Wang

Reputation: 23

A homework is about use macro

This questions is about my homework.
This topic is need to use like:

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

The content of the question is to make this code run normally:

#include <stdio.h>

GenerateShowValueFunc(double)
GenerateShowValueFunc(int)

int main()
{

    double i = 5.2;
    int j = 3;

    showValue_double(i);
    showValue_int(j);

}

The result of the operation is like this:

i=5.2000
j=3

And this code is my current progress, but there are have problems:

#include <stdio.h>

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

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

GenerateShowValueFunc(double)
GenerateShowValueFunc(int)

int main()
{

    double i = 5.2;
    int j = 3;

    showValue_double(i);
    showValue_int(j);

}

I don’t know how to make the output change with the type, and I don’t know how to display the name of the variable. OAO


This original task description: Please refer to ShowValue.c below:

#include <stdio.h>

GenerateShowValueFunc(double)
GenerateShowValueFunc(int)

int main()
{

    double i = 5.2;
    int j = 3;

    showValue_double(i);
    showValue_int(j);

}

Through [GenerateShowValueFunc(double)] and [GenerateShowValueFunc(int)] these two lines macro call, can help us to generated as [showValue_double( double )] and [showValue_int( int )] function, And in main() function called. The execution result of this program is as follows:

i=5.2000
j=3

Please insert the code that defines GenerateShowValueFunc macro into the appropriate place in the ShowValue.c program, so that this program can compile and run smoothly.

Upvotes: 2

Views: 111

Answers (2)

Yunnosch
Yunnosch

Reputation: 26763

Without changing the shown C-code (i.e. only doing macros), which I consider a requirement, the following code has the required output:

#include <stdio.h>

#define showValue_double(input) \
showValueFunc_double(#input"=%.4f\n" , input)

#define showValue_int(input) \
showValueFunc_int(#input"=%d\n" , 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);

}

Output:

i=5.2000
j=3

Note that I created something of a lookup-table for type-specific format specifiers. I.e. for each type to be supported you need to add a macro #define showValue_ .... This is also needed to get the name of the variable into the output.

This uses the fact that two "strings" are concatenated by C compilers, i.e. "A""B" is the same as "AB". Where "A" is the result of #input.
The rest, i.e. the required function definition is very similar to the teacher-provided example, using the ## operator.

Note, this is if the variable name has to correctly be mentioned in the output.
With out the i = things would be easier and would more elegantly use the generated functions WITHOUT having the called showValue_double(i); be explicit macros. I.e. the functions generated are 1:1 what is called from main(). I think that might be what is really asked. Let me know if you want that version.

Upvotes: 2

Lundin
Lundin

Reputation: 214860

A quick & dirty solution would be:

type showValue_##type(type x)\
{\
    const char* double_fmt = "=%f\n";\
    const char* int_fmt = "=%d\n";\
    printname(x);\
    printf(type##_fmt, x);\
    return 0;\
}

The compiler will optimize out the variable that isn't used, so it won't affect performance. But it might yield warnings "variable not used". You can add null statements like (void)double_fmt; to silence it.


Anyway, this is all very brittle and bug-prone, it was never recommended practice to write macros like these. And it is not how you do generic programming in modern C. You can teach your teacher how, by showing them the following example:

#include <stdio.h>

void double_show (double d)
{
  printf("%f\n", d);
}

void int_show (int i)
{
  printf("%d\n", 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);
}

This uses the modern C11/C17 standard _Generic keyword, which can check for types at compile-time. The macro picks the appropriate function to call and it is type safe. The caller doesn't need to worry which "show" function to call nor that they pass the correct type.

Upvotes: 3

Related Questions