In pvalue.h file:
int* pv_int( int value );
In pvalue.c file:
int* pv_int( int value )
{
static int si = 0;
si = value;
return &si;
}
I'm trying to use these macros to template these definitions for other
types, but its not working.
#define PVALUE_PROTO( TYPE ) TYPE* c_pv_##TYPE( TYPE value )
#define PVALUE_IMPL( TYPE )\
TYPE* c_pv_##TYPE( TYPE value )\
{\
static TYPE sv = 0;\
sv = value;\
return &sv;\
}
I'm getting a syntax error and can't figure out what I'm doing wrong.
Anyone can help?
--
comp.lang.c.moderated - moderation address: cl...@plethora.net -- you must
have an appropriate newsgroups line in your header for your mail to be seen,
or the newsgroup name in square brackets in the subject line. Sorry.
I trust you're aware that pv_int will return a pointer to the same int
object each time it's called, so this:
int *x = pv_int(10);
int *y = pv_int(20);
will result in both *x and *y being equal to 20. There's only one
"si", shared among all calls to pv_int.
> I'm trying to use these macros to template these definitions for other
> types, but its not working.
>
> #define PVALUE_PROTO( TYPE ) TYPE* c_pv_##TYPE( TYPE value )
>
> #define PVALUE_IMPL( TYPE )\
> TYPE* c_pv_##TYPE( TYPE value )\
> {\
> static TYPE sv = 0;\
> sv = value;\
> return &sv;\
> }
>
> I'm getting a syntax error and can't figure out what I'm doing wrong.
> Anyone can help?
One thing you're doing wrong is not showing us the code that produces
the syntax error. There's no syntax error in the macro definitions'
any syntax error could occur only when you invoke them.
One likely problem is that you're using them like this:
PVALUE_PROTO(int);
PVALUE_IMPL(int);
If so, you have an extraneous semicolon after the function
definition. The way you've written the macros, you must have a
semicolon after an invocation of PVALUE_PROTO, and you can't have
a semicolon after PVALUE_IMPL.
Here's a program that uses your macros:
#define PVALUE_PROTO( TYPE ) TYPE* c_pv_##TYPE( TYPE value )
#define PVALUE_IMPL( TYPE )\
TYPE* c_pv_##TYPE( TYPE value )\
{\
static TYPE sv = 0;\
sv = value;\
return &sv;\
}
PVALUE_PROTO(int);
PVALUE_IMPL(int)
int main(void)
{
int *x = c_pv_int(10);
int *y = c_pv_int(20);
printf("x %s y, *x = %d, *y = %d\n",
x == y ? "==" : "!=",
*x,
*y);
return 0;
}
The output is:
x == y, *x = 20, *y = 20
If that doesn't solve the problem, show us a complete translation
unit that exhibits the problem (cut-and-paste, don't re-type),
along with the exact error message you get.
If your compiler has an option to show you the output of the
preprocessor, it can be useful for this kind of thing. (gcc,
for example, uses the "-E" option for this.)
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
> I'm trying to use these macros to template these definitions for other
> types, but its not working.
"It's not working" doesn't tell anybody anything about the actual
problem. You'll have to be more concrete. What did you do, what did it
do, what did you think it should do, and why should it have done exactly
that?
> I'm getting a syntax error and can't figure out what I'm doing wrong.
Start by showing us the actual code that you got that syntax error in,
and the exact text of the error message.
Yes, that is the intent. The basis for this pointer-to-value function
is to take literal values and pass them to a function that expects a
void*. I'll demonstrate with a small snippet.
\code
void _gc_queue_push_back( c_queue_t* queue, void* object, size_t sz );
\endcode
This is a generic function that takes any object and its size and
places it at the end of the queue.
\code
#define c_queue_push_back( queue, object, type ) (_gc_queue_push_back
( (queue), (object), sizeof(type) ))
\endcode
This is a macro that translates the type specific queue push operation
into the generic function.
However, to support pushing a literal integer, I would need a
temporary object to pass the address of when copying the integer into
the queue.
\code
int value = 10;
c_queue_t* q = c_queue_new( int, 10 );
c_queue_push_back( q, &value, int );
\endcode
I can accomplish the same mechanism with this pointer-to-value
function, without the extra variable.
\code
c_queue_t* q = c_queue_new( int, 10 );
c_queue_push_back( q, c_pv_int( 10 ), int );
\endcode
Since the queue copies any object to its internal memory, I don't mind
that the function returns the same pointer over again. There could be
a better idiom to implement this, but this is what I came up with.
> > I'm trying to use these macros to template these definitions for other
> > types, but its not working.
>
> > #define PVALUE_PROTO( TYPE ) TYPE* c_pv_##TYPE( TYPE value )
>
> > #define PVALUE_IMPL( TYPE )\
> > TYPE* c_pv_##TYPE( TYPE value )\
> > {\
> > static TYPE sv = 0;\
> > sv = value;\
> > return &sv;\
> > }
>
> > I'm getting a syntax error and can't figure out what I'm doing wrong.
> > Anyone can help?
>
> One thing you're doing wrong is not showing us the code that produces
> the syntax error. There's no syntax error in the macro definitions'
> any syntax error could occur only when you invoke them.
Fair enough, my development environment for this project is required
not to have internet access, so I was lazy on that part.
> One likely problem is that you're using them like this:
>
> PVALUE_PROTO(int);
> PVALUE_IMPL(int);
>
> If so, you have an extraneous semicolon after the function
> definition. The way you've written the macros, you must have a
> semicolon after an invocation of PVALUE_PROTO, and you can't have
> a semicolon after PVALUE_IMPL.
I didn't make the syntax mistake you mentioned up above, but you have
brought up a usability issue where a semicolon is required for one and
not the other, potentially leading to confusion. I think I'll add a
semicolon to the PROTO macro to make the interface more consistent.
I tried your example and it works fine just. The C_PV_IMPL
instantiations are in a library source file so I double checked it and
found that in the pvalue.c file I didn't include the pvalue.h header
file. I blame it on end of the day programming :P
I appreciate your helpful response.
Best regards,
John Dill
C99:
---
#include <stdio.h>
int foo(int *x) {
printf("%d\n", *x);
}
#define ANONYMOUS_X(type, value) ((type *) &(struct { type x; }) { value })
int
main(void) {
foo(ANONYMOUS_X(int, 4));
return 0;
}
---
The address of a struct is always the address of its first member, so
make an anonymous struct type with only that member, and take the
address of a struct literal of that type.
-s
--
Copyright 2009, all wrongs reversed. Peter Seebach / usenet...@seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
and what problem are you trying to solvr by doing that. Often there is a
much better solution doing it entirely differently. And most experienced
C++ programmers try to avoid macros unless they really are unavoidable.
#define C_PVALUE_PROTO( NAME, TYPE ) TYPE* c_pv_##NAME( TYPE value );
#define C_PVALUE_IMPL( NAME, TYPE )\
TYPE* c_pv_##NAME( TYPE value )\
{\
static TYPE sv = 0;\
sv = value;\
return &sv;\
}
Now I can do this.
C_PVALUE_PROTO( uchar, unsigned char )
C_PVALUE_PROTO( pointer, void* )
C_PVALUE_IMPL( uchar, unsigned char )
C_PVALUE_IMPL( pointer, void* )
Interesting. <--Puts example into mental toolbox--> I'll try it out
and see how it goes. Certainly cleaner than having to instantiate
those macros for each type.