problem with macro

R

Roman Mashak

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: (e-mail address removed)
 
E

Emmanuel Delahaye

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: (e-mail address removed)

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.
 
R

Roman Mashak

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: (e-mail address removed)
 
M

Michael Mair

Roman said:
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
 
R

Roman Mashak

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: (e-mail address removed)
 
L

Lawrence Kirby

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
 
M

Michael Mair

Roman said:
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, <[email protected]>, 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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top