problem with macro

  • Follow


Hello, All!

I would like to use this macro to substitute type of variable, but it 
doesn't work by now:

typedef enum table_type_e {
 INT,
 FLOAT,
 DOUBLE
} table_type_t;

#define TYPE(t) ((t == INT) ? int :\
    (t == FLOAT) ? float :\
    (t == DOUBLE) ? double : void )

int main()
{
.....
   table_type_t t;
   t = INT;
   TYPE(t) p;
......
}

I'd like 'p' be has 'int' type. But during compilation I get this error: 
parse error before "int"  It points directly to "TYPE(t) p" string.
Am I breaking the standard or making some C-specific mistake?

PS. if it's important, I'm using gcc-3.2.2

With best regards, Roman Mashak.  E-mail: mrv@tusur.ru 


0
Reply mrv (331) 6/18/2005 7:38:26 AM

Roman Mashak wrote on 18/06/05 :
> Hello, All!
>
> I would like to use this macro to substitute type of variable, but it doesn't 
> work by now:
>
> typedef enum table_type_e {
>  INT,
>  FLOAT,
>  DOUBLE
> } table_type_t;
>
> #define TYPE(t) ((t == INT) ? int :\
>     (t == FLOAT) ? float :\
>     (t == DOUBLE) ? double : void )
>
> int main()
> {
> ....
>    table_type_t t;
>    t = INT;
>    TYPE(t) p;
> .....
> }
>
> I'd like 'p' be has 'int' type. But during compilation I get this error: 
> parse error before "int"  It points directly to "TYPE(t) p" string.
> Am I breaking the standard or making some C-specific mistake?
>
> PS. if it's important, I'm using gcc-3.2.2
>
> With best regards, Roman Mashak.  E-mail: mrv@tusur.ru

You can't do that. The usual trick is hard coded :

typedef enum
{
   INT,
   FLOAT,
   DOUBLE
}
table_type_e;


void f (table_type_e t)
{
   switch (t)
   {
   case INT:
      {
         int p;
         /* <...> */
      }
      break;

   case FLOAT:
      {
         float p;
         /* <...> */
      }
      break;

   case DOUBLE:
      {
         double p;
         /* <...> */
      }
      break;
   }
}

int main (void)
{
   f (INT);
   return 0;
}

-- 
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Mal nommer les choses c'est ajouter du malheur au
monde." -- Albert Camus.

0
Reply emdel (952) 6/18/2005 7:54:46 AM


Hello!

Actually the goal I'm chasing for is the following.  I'm implementing 
function, searching elements in the array by its own algorithm. The problem 
is that array can be of different types: int, float, double, long etc. So, 
I'd prefer to implement everything in one function.

typedef enum table_type_e {
    INT,
    FLOAT,
    DOUBLE
} table_type_t;

The function is declared in this wway:

// 'tbl' is array of elements, 'key' is key of search, 'nm' - number of 
elements and 't' is a type of array I pass to function
int m_search(void *tbl, void *key, size_t nm, table_type_t t)
{
....
}

int main()
{
    int tbl[5] = {1,2,3,4,5};
    int key=2;
    ...
}

The first problem I faced is I must make type-casting in the m_search(), 
that's why I transfer array type to it. So, if I use 'switch-case' way the 
function will be too fat :)  that's why I'm interested in making some macro 
to simplify, if you say it's too hard - may be there is another way for 
type-casting in my situation?

Thanks in advance for any help!

With best regards, Roman Mashak.  E-mail: mrv@tusur.ru 


0
Reply mrv (331) 6/18/2005 8:16:31 AM

Roman Mashak wrote:
> Hello, All!
> 
> I would like to use this macro to substitute type of variable, but it 
> doesn't work by now:
> 
> typedef enum table_type_e {
>  INT,
>  FLOAT,
>  DOUBLE
> } table_type_t;
> 
> #define TYPE(t) ((t == INT) ? int :\
>     (t == FLOAT) ? float :\
>     (t == DOUBLE) ? double : void )
> 
> int main()
> {
> ....
>    table_type_t t;
>    t = INT;
>    TYPE(t) p;

There is no generic "conditional typing" in C.

Okay, let's see what you have got after the preprocessor ran over
it (or, after the respective translation phase, for the nitpickers):

   TYPE(T) p;
(T instead of t for clarity) becomes

   ((T == INT) ? int : (T == FLOAT) ? float : (T == DOUBLE) ? double : 
void ) p;

So, you want from the preprocessor (or, before the respective
translation phases) to analyse your code and reduce it to either
int or float or double or void (BTW: what will you do with a "variable"
of type void).
If you go a step further, T could be determined at runtime by reading
some user input. This cannot work.

Apart from that, the conditional operator is subject to the following
constraints:

,- C99, 6.5.15#2, #3 ---
|
| The first operand shall have scalar type.
|
| One of the following shall hold for the second and third operands:
| * both operands have arithmetic type;
| * both operands have the same structure or union type;
| * both operands have void type;
| * both operands are pointers to qualified or unqualified versions of
|   compatible types;
| * one operand is a pointer and the other is a null pointer constant;
|   or
| * one operand is a pointer to an object or incomplete type and the
|   other is a pointer to a qualified or unqualified version of void.
`----

So, no operand can be a _type_.
Now, you could have the bright idea to give p as a second parameter
to the macro. This won't work either.
What you _can_ do is something like

  typedef struct {
    table_type_t type;
    union {
      int    IntVal;
      float  FltVal;
      double DblVal;
    } value;
  } alltypes_t;

combined with a standard way to initialise variables of this type
and a way of error handling.

Cheers
  Michael
> .....
> }
> 
> I'd like 'p' be has 'int' type. But during compilation I get this error: 
> parse error before "int"  It points directly to "TYPE(t) p" string.
> Am I breaking the standard or making some C-specific mistake?
> 
> PS. if it's important, I'm using gcc-3.2.2
> 
> With best regards, Roman Mashak.  E-mail: mrv@tusur.ru 
> 
> 


-- 
E-Mail: Mine is an   /at/ gmx /dot/ de   address.
0
Reply Michael.Mair (1492) 6/18/2005 8:17:00 AM

Hello, Michael!
You wrote  on Sat, 18 Jun 2005 10:17:00 +0200:

 MM> So, no operand can be a _type_.
 MM> Now, you could have the bright idea to give p as a second parameter
 MM> to the macro. This won't work either.
 MM> What you _can_ do is something like

 MM>   typedef struct {
 MM>     table_type_t type;
 MM>     union {
 MM>       int    IntVal;
 MM>       float  FltVal;
 MM>       double DblVal;
 MM>     } value;
 MM>   } alltypes_t;

 MM> combined with a standard way to initialise variables of this type
 MM> and a way of error handling.
Thanks for detailed explanation, but I'm not sure what I'm supposed to do 
with structure you offered? Use it as an argument for my taget function and 
pass pointer to 'alltypes_t' for the function, am I right?


With best regards, Roman Mashak.  E-mail: mrv@tusur.ru 


0
Reply mrv (331) 6/18/2005 8:37:16 AM

On Sat, 18 Jun 2005 17:16:31 +0900, Roman Mashak wrote:

> Hello!
> 
> Actually the goal I'm chasing for is the following.  I'm implementing 
> function, searching elements in the array by its own algorithm.

C is statically typed, any particular point in the evaluation of an
expression there is only ever one type. If you want to handle multiple
types you need to have separate code for each type you handle. You can
copy any type of object by treating it as an array of unsigned char, which
is in effect what memcpy() does. Take for example the standard library
function qsort(). It can sort arrays of any element type; it can copy
elements internally but it can't interpret the data in the elements.
Therefore it requires you to provide a comparison function written for the
specific element types to do this.

> The problem 
> is that array can be of different types: int, float, double, long etc. So, 
> I'd prefer to implement everything in one function.
> 
> typedef enum table_type_e {
>     INT,
>     FLOAT,
>     DOUBLE
> } table_type_t;
> 
> The function is declared in this wway:
> 
> // 'tbl' is array of elements, 'key' is key of search, 'nm' - number of 
> elements and 't' is a type of array I pass to function
> int m_search(void *tbl, void *key, size_t nm, table_type_t t)
> {
> ...
> }

Your function will need to contain separate code for each of the types it
supports. A switch statement is a reasonable way to do this.

> int main()
> {
>     int tbl[5] = {1,2,3,4,5};
>     int key=2;
>     ...
> }
> 
> The first problem I faced is I must make type-casting in the m_search(), 
> that's why I transfer array type to it. So, if I use 'switch-case' way the 
> function will be too fat :)

What's your criterion for "too fat"?

> that's why I'm interested in making some macro 
> to simplify, if you say it's too hard - may be there is another way for 
> type-casting in my situation?

Macros simply expand to code which is then compiled as normal, so you
can't do anything with a macro that you can't do without one. You might be
able to make the source code shorter by replacing repetitive sequences of
code with macros which expand during translation, but the object code
won't be any smaller.

Lawrence
0
Reply lknews (877) 6/18/2005 11:52:50 AM

Roman Mashak wrote:
> Hello, Michael!
> You wrote  on Sat, 18 Jun 2005 10:17:00 +0200:
> 
>  MM> So, no operand can be a _type_.
>  MM> Now, you could have the bright idea to give p as a second parameter
>  MM> to the macro. This won't work either.
>  MM> What you _can_ do is something like
> 
>  MM>   typedef struct {
>  MM>     table_type_t type;
>  MM>     union {
>  MM>       int    IntVal;
>  MM>       float  FltVal;
>  MM>       double DblVal;
>  MM>     } value;
>  MM>   } alltypes_t;
> 
>  MM> combined with a standard way to initialise variables of this type
>  MM> and a way of error handling.
> Thanks for detailed explanation, but I'm not sure what I'm supposed to do 
> with structure you offered? Use it as an argument for my taget function and 
> pass pointer to 'alltypes_t' for the function, am I right?

 From your other posting, <d90l8r$1f2b$1@relay.tomsk.ru>, I infer that
you do not wish to represent one out of a number of types for which
the above can cater but that you want to have a "template" functionality
which works for arrays of arbitrary type.
This is not possible -- you need separate code for every type.

Cheers
  Michael
-- 
E-Mail: Mine is an   /at/ gmx /dot/ de   address.
0
Reply Michael.Mair (1492) 6/18/2005 5:05:47 PM

6 Replies
33 Views

(page loaded in 0.065 seconds)

Similiar Articles:













7/28/2012 10:01:30 AM


Reply: