token concat

A

atorrses

Hi
Please consider this code :

#define CONCAT(token,digit) token##digit

enum EN {
elem ;
} ;

struct ST {
int elem1;
int elem2;
} ;

void func (struct ST *st){
unsigned d;
for ( d=1 ; d <= 2 ; d++ )
if ( st->CONCAT(elem,d) == 0 )
st->CONCAT(elem,d) = 1;
return ;
} ;


As you may infer from the code the purpose is to change the value of
first 0-valued element of structure to 1.
I wonder if this could be done this way.Here compiler says elemd is
not a member of struct.I tried other things like st->CONCAT(elem,*&d)
but it did not work too.Also note that EN and ST can have several
members in same style but also note that ST can be a compound
structure.
Hints are appreciated on what to do here and also other methods to do
this in general.

void func2 ( struct ST *st ){
unsigned d;
if ( st->elem1 == 0)
st->elem1=1;
else if ( st->elem2 == 0)
st->elem2 = 1;
else {} ;

return ;
};
 
N

Nate Eldredge

Hi
Please consider this code :

#define CONCAT(token,digit) token##digit

enum EN {
elem ;
} ;

struct ST {
int elem1;
int elem2;
} ;

void func (struct ST *st){
unsigned d;
for ( d=1 ; d <= 2 ; d++ )
if ( st->CONCAT(elem,d) == 0 )
st->CONCAT(elem,d) = 1;
return ;
} ;


As you may infer from the code the purpose is to change the value of
first 0-valued element of structure to 1.

In which case you probably meant to do the braces differently, so that
the `return' is part of the block following the `if'.
I wonder if this could be done this way.Here compiler says elemd is
not a member of struct.I tried other things like st->CONCAT(elem,*&d)
but it did not work too.Also note that EN and ST can have several
members in same style but also note that ST can be a compound
structure.
Hints are appreciated on what to do here and also other methods to do
this in general.

This won't work. Token concatenation is done in a pass before
compilation and gives you the literal concatenation of the tokens.
`CONCAT(elem,d)' expands to `elemd'. You can't get the value of the
variables corresponding to those tokens; they aren't known until run
time.

The simplest solution to your problem would be to use an array in your
struct instead of separate members.

struct ST {
int elem[2];
};

void func (struct ST *st) {
unsigned d;
for (d = 0; d <= 1; d++) {
if (st->elem[d] == 0) {
st->elem[d] = 1;
return;
}
}
}

Note the zero-based indexing, of course.

If for some reason they have to be separate members (perhaps they are of
different types, or can't be located contiguously), AFAIK there is no
portable way to operate on all of them except by dealing with each one
individually, like your func2. You can make it a little less typing
with a macro:

struct ST {
int elem1;
int elem2;
};

#define CONCAT(token,digit) token##digit
void func (struct ST *st) {
#define FOO(d) if (st->CONCAT(token,d) == 0) { st->CONCAT(token,d) = 1; return; }
FOO(1)
FOO(2)
#undef FOO
}

If there are a large number of elements, you could write a short program
in your favorite language that would generate the appropriate C code,
which could then be included in your program.

#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i;
printf("void func(struct ST *st) {\n");
for (i = 1; i < 500; i++)
printf("\tif (st->elem%d == 0) {\n\t\tst->elem%d = 1;\t\treturn;\t}\n", i, i);
printf("}\n");
return EXIT_SUCCESS;
}
 
T

Thad Smith

Nate said:
In which case you probably meant to do the braces differently, so that
the `return' is part of the block following the `if'.
....

The simplest solution to your problem would be to use an array in your
struct instead of separate members.

I agree.
struct ST {
int elem[2];
};

void func (struct ST *st) {
unsigned d;
for (d = 0; d <= 1; d++) {
if (st->elem[d] == 0) {
st->elem[d] = 1;
return;
}
}
}

Note the zero-based indexing, of course.

If for some reason they have to be separate members (perhaps they are of
different types, or can't be located contiguously), AFAIK there is no
portable way to operate on all of them except by dealing with each one
individually, like your func2.

Another alternative is to declare a union of an array and a struct
containing the individual elements, assuming that the individual
elements are all the same type. The data can be addressed either way,
but it is not transparent, since you must additionally specify the union
member (a non-standard C extension on some compilers allows the union
member name to be omitted).

You can make it a little less typing
with a macro:

struct ST {
int elem1;
int elem2;
};

#define CONCAT(token,digit) token##digit
void func (struct ST *st) {
#define FOO(d) if (st->CONCAT(token,d) == 0) { st->CONCAT(token,d) = 1; return; } s /token/elem/
FOO(1)
FOO(2)
#undef FOO
}

This works, but I recommend against it except for special circumstances
because it is more confusing to the average programmer. I would do
something like

if (st->elem1 == 0) st->elem1 = 1;
else if (st->elem2 == 0) st->elem2 = 1;
...

lining up the common elements vertically so that the pattern can be
easily seen.
If there are a large number of elements, you could write a short program
in your favorite language that would generate the appropriate C code,
which could then be included in your program.

There are cases where this makes sense.

Good response, Nate.
 
C

c.prog.fan

Thanks Nate Eldredge and Thad Smith .
Well nate's response seems very good to me also.
In which case you probably meant to do the braces differently, so that
the `return' is part of the block following the `if'.

Yes ; ok I confess this was a rewrite of a more complex code and thus
the missing return.
The simplest solution to your problem would be to use an array in your
struct instead of separate members.

Good idea but the structure has been around for a while which means
some code depends on it.
#define CONCAT(token,digit) token##digit
void func (struct ST *st) {
#define FOO(d) if (st->CONCAT(token,d) == 0) { st->CONCAT(token,d) = 1; return; }
FOO(1)
FOO(2)
#undef FOO

}

This should work anyway and I in fact tried this.I like macros ;
Great !
include <stdio.h>
#include <stdlib.h>
int main(void) {
int i;
printf("void func(struct ST *st) {\n");
for (i = 1; i < 500; i++)
printf("\tif (st->elem%d == 0) {\n\t\tst->elem%d = 1;\t\treturn;\t}\n", i, i);
printf("}\n");
return EXIT_SUCCESS;

Hmm , can you write a similar program for me to write all the codes I
intend to ?
:)
 

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

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top