0

I have a variable that I do not type of. So to print that I do not know whether to use %d or %f. For this I want to check its type before printing.

Now to check its type I want to use like this:

if (typeof(int) == voltage) {
snprintf(chars, sizeof(chars), "%d", voltage);
}

Now this is not valid.

I need a way to check the variable type.

I am testing with two variables, but I think following is not valid either.

And how to use this getIntType function/(What is it called? macro?) that I got and modified from here and here?

#define getIntType(a,b)  ({ __auto_type _a = (a); __auto_type _b = (b); _a == typeof(int) ? _a : _b; });

        int a = 10;
        double b = 20.0;
    int x = getIntType(a,b)==?; //How to call and how to store in type var of this x?

and how to return value from macro/ how to use this?

        #define typecheck(type,x) \
        ({  type __dummy; \
        typeof(x) __dummy2; \
        (bool)(&__dummy == &__dummy2); \
        }) // How to return value to check?


    //Then how to check?
        int a = 10;
        double b = 20.0;
       //int x = getIntType(a,b)? a : b;

        //bool isInt = typecheck(typeof(int), a);
sepp2k
  • 363,768
  • 54
  • 674
  • 675
Rifat
  • 1,700
  • 3
  • 20
  • 51
  • 1
    `typeof` is a GCC extension, not a standard operator. – Barmar Mar 30 '20 at 05:00
  • I read that from other questions in SO. I need to check type of a variable. So what to use? – Rifat Mar 30 '20 at 05:01
  • It's not a runtime value, it's something you can use in declarations. See https://stackoverflow.com/questions/12081502/typeof-operator-in-c – Barmar Mar 30 '20 at 05:01
  • This not specifically about type of extension, it is about checking a variable type. – Rifat Mar 30 '20 at 05:02
  • It's like a macro that expands into the type declaration. – Barmar Mar 30 '20 at 05:02
  • I know what you're asking. The problem is that it doesn't expand into an expression with a value, so there's nothing you can check. – Barmar Mar 30 '20 at 05:03
  • 1
    How can you not know the type of the `voltage` variable? Didn't you declare it earlier in the program? – Barmar Mar 30 '20 at 05:03
  • Also, the syntax is `typeof(voltage)`, not `typeof(int)`. – Barmar Mar 30 '20 at 05:04
  • voltage variable is coming from an API. If I use `%d` it shows a number(3) but that could be a float value but using `%f` it shows 0; Then it is for a placeholder `typeof(int)`. You will use `typeof(voltage)` with what to compare? int is required to determine a specific type. – Rifat Mar 30 '20 at 05:12
  • 1
    It doesn't matter where it's coming from. You need to declare the variable before you can read the API response into it. – Barmar Mar 30 '20 at 05:13
  • If you're using C11, you probably want to check [generics](http://www.robertgamble.net/2012/01/c11-generic-selections.html). – vgru Mar 30 '20 at 05:14
  • @Barmar it is declared and assigned as an enumeration. It gets value from: `battery_get_level_status(&battery_status)`. – Rifat Mar 30 '20 at 05:16
  • 1
    @Rifat: what Barmar is saying is that this function must have a known declaration in C, i.e. `void battery_get_level_status(double * output)`, meaning that `output` can only be a `double`. So generics will help you if you want to reuse the same function for multiple different types, but you will know the actual type of the variable at the moment of the invocation, because C simply doesn't support polymorphism or inheritance. In other words, if you hover the mouse over `battery_status` in your favorite IDE, you will likely get a tooltip. What does this tooltip say? – vgru Mar 30 '20 at 05:18
  • @Rifat Did you mean a `union` rather than enumeration? There's no automatic way to know which member of a union was last assigned. Perhaps you should look into using a discriminated union. – Barmar Mar 30 '20 at 05:23
  • @Groo, what if your favorite IDE is `notepad`? Or `edlin`? :-) – paxdiablo Mar 30 '20 at 05:23
  • @Groo Thanks for clarification. It does indeed says a type which is int. – Rifat Mar 30 '20 at 05:26

1 Answers1

1

If you want a portable solution, you can look into C11 generic macros, the poor C programmer's equivalent to C++ polymorphism :-)

The following program shows how you can use it:

#include <stdio.h>

#define Output(buff, sz, T) _Generic((T), \
    char *: OutputS, \
    double: OutputD, \
    int: OutputI \
)(buff, sz, T)
void OutputS(char *buff, size_t sz, char *s)  { snprintf(buff, sz, "S %s", s); }
void OutputD(char *buff, size_t sz, double d) { snprintf(buff, sz, "D %f", d); }
void OutputI(char *buff, size_t sz, int i)    { snprintf(buff, sz, "I %d", i); }

int main() {
    char buff[100];
    Output(buff, sizeof(buff), "hello"); puts(buff);
    Output(buff, sizeof(buff), 5);       puts(buff);
    Output(buff, sizeof(buff), 3.14159); puts(buff);
}

You can see that the correct function is called based on the data type:

S hello
I 5
D 3.141590
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • This answer is cool, does what I expected on the question. But after strcat operation with buff to store all values altogether (`char *str[1024]; strcat(str,buff)`), I get some garbage values at the beginning that I do not know where it is coming from or how to remove it. Can you please give a solution? – Rifat Mar 30 '20 at 06:35
  • 2
    @Rifat, that should probably be a different question but here goes. The correct definition would be `char str[1024]` for a start (you want an array of characters, not an array of character pointers). And, when you create variables on the stack without initialising, they have arbitrary values. So either `char str[1024] = {0}` or make the first operation a `strcpy` (which creaters a new string) rather than `strcat` (which appends to an existing string). – paxdiablo Mar 30 '20 at 07:03