[Need C/C++ Experts' Help] Return lvalue from Condtional Expression

P

perry.yuan

Hi there,

I got a problem: how to return an lvalue from conditional expression in
C programming language. Any solution or suggestion to my problem in
either C or C++ is welcome.

On the CPU (actually it is a DSP), memory is addressed in 16 bit unit
(called word).

There is a struct of variable size (in pseudo code):

typedef struct V_STRUCT {
unsigned length : 8; /* 8 bit field. Value range [1..99] */
unsigned_8_bit_field varray[length];
} v_struct_t;

e.g. if the value of the field length is 4, the struct will look like
(in pseudo code):

typedef struct V_STRUCT {
unsigned length : 8; /* Value 4. MSB of Word #1. */
unsigned varray[0]: 8; /* LSB of Word #1. */

unsigned varray[1]: 8; /* MSB of Word #2. */
unsigned varray[2]: 8; /* LSB of Word #2. */

unsigned varray[3]: 8; /* MSB of Word #3. */
unsigned alignment_filling: 8; /* LSB of Word #3. */
} v_struct_t;

The real definition of the struct is:

typedef struct V_STRUCT {
unsigned length : 8;
unsigned varray : 8;
} v_struct_t;

I would like to provide a convenient macro to access element of the
varray:

typedef struct DSPWORD {
unsigned msb : 8;
unsigned lsb : 8;
} dspword_t;

#define ELEMENT_OF_VARRAY( v_struct, idx_of_varray ) \
( ( (idx_of_varray) & 0x0001 ) \
? \
( ( ( (dspword_t *) &(v_struct) ) + ( ( (idx_of_varray) + 1) >> 1
) )->msb ) \
: \
( ( ( (dspword_t *) &(v_struct) ) + ( ( (idx_of_varray) + 1) >> 1
) )->lsb ) \
)

The problem is that, according to the C99 Standard, conditional
expression could not return an lvalue so that I can only use the macro
ELEMENT_OF_VARRAY as rvalue but not as lvalue. However, I'd like use it
as both rvalue and lvalue.

Any solution/trick/suggestion to that? TIA.
 
T

tedu

perry.yuan said:
#define ELEMENT_OF_VARRAY( v_struct, idx_of_varray ) \
( ( (idx_of_varray) & 0x0001 ) \
? \
( ( ( (dspword_t *) &(v_struct) ) + ( ( (idx_of_varray) + 1) >> 1
) )->msb ) \
: \
( ( ( (dspword_t *) &(v_struct) ) + ( ( (idx_of_varray) + 1) >> 1
) )->lsb ) \
)

The problem is that, according to the C99 Standard, conditional
expression could not return an lvalue so that I can only use the macro
ELEMENT_OF_VARRAY as rvalue but not as lvalue. However, I'd like use it
as both rvalue and lvalue.

you can do two things. one is to create a "write" macro:

#define SET_ELEMENT(v_struct, idx, value) \
if (..) { v_struct.x = value; } else { v_struct.y = value; }

or you can use a function to return the right address, and have the
macro deref it for you.

inline int *get_vstruct_addr(struct vstruct *p, int idx) { return
&p->field; }
#define ELEMENT_OF_VARRAY(vstruct, idx) (*get_vstruct_addr(&vstruct,
idx))
 
P

perry.yuan

you can do two things. one is to create a "write" macro:

#define SET_ELEMENT(v_struct, idx, value) \
if (..) { v_struct.x = value; } else { v_struct.y = value; }

or you can use a function to return the right address, and have the
macro deref it for you.

inline int *get_vstruct_addr(struct vstruct *p, int idx) { return
&p->field; }
#define ELEMENT_OF_VARRAY(vstruct, idx) (*get_vstruct_addr(&vstruct,
idx))

Thanks for your reply.

But I need an expression (could be embedded in any statement as user
likes) instead of a statement.

get_vstruct_addr() doesn't work because of its returning an address of
bit field.
 
P

pete

perry.yuan said:
Hi there,

I got a problem: how to return an lvalue from
conditional expression in
C programming language. Any solution or suggestion to my problem in
either C or C++ is welcome.
The problem is that, according to the C99 Standard, conditional
expression could not return an lvalue so that I can only use the macro
ELEMENT_OF_VARRAY as rvalue but not as lvalue.
However, I'd like use it as both rvalue and lvalue.

Any solution/trick/suggestion to that? TIA.

(*(condition ? pointer_1 : pointer_2))
 
G

Guest

perry.yuan said:
Thanks for your reply.

But I need an expression (could be embedded in any statement as user
likes) instead of a statement.

get_vstruct_addr() doesn't work because of its returning an address of
bit field.

You can rewrite the first suggestion as a single expression:
#define SET_ELEMENT(v_struct, idx, value) \
((...) ? ((v_struct).x = (value)) : ((v_struct).y = (value)))

Some of the parentheses may be unnecessary, but I haven't checked,
since they don't hurt. If you're working with bit-fields, I think
that's the closest you'll get to what you want.
 
P

perry.yuan

Richard said:
1. Don't Do That, it's obfuscatory;
2. Read the bleedin' FAQ: <http://c-faq.com/expr/qcolonlhs.html>.

Richard

Thanks, Richard and all others.

My working environment is in a rather old C language programming style
so that a macro seems to be the best fit. I'd like to write in macro an
expression that could be embedded in other expressions as either rvalue
or lvalue.

The mean

*((condition) ? &a : &b) = complicated_expression;

is a good idea to me. However, in my case, it still doesn't work: I
could not take address of bit field. It seems I have to design a
function instead of a expression.

Thanks again.
 
A

Ancient_Hacker

perry.yuan wrote:

I don't think you can ever use a bitfield in a conditional lvalue. You
see it's a very tricky thing to do at run-time-- the compiler would
have to conditionally jump to different bits of code depending on what
was being stored into. This is theoretically doable, but it clashes
with the way most optimizers want the parse tree to look like.
 
T

tedu

perry.yuan said:
get_vstruct_addr() doesn't work because of its returning an address of
bit field.

does it need to be a bitfield? if your compiler has 8bit chars, can't
you just use char?
 

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

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top