----- Original Message ----- 
From: "nataraj" 
To: "Vijay Kumar R Zanvar" 
Sent: Monday, April 19, 2004 12:31 PM
Subject: c code

> Hi Vijay,
>  
> find out the problem in below code...i want address of first member 
> of structure in MACRO.
>  
> Regards
> Nataraj
>  
> #include 
>  
> typedef struct A{
>     char b;
>     int c;
> }A;
>  
> #define STA1(t1) { A *p; \
>                    p=t1; \
>                    (p)?((int)&(p->b)):(0);  }
> 
> int
> main()
> { 
>     A test; 
>     int k = 0;
>  
>     test.b=4;
>     test.c=1; 
>     k=STA1(&test); 

Things get wrong here.  The macro, STA1, expands into a block of statements.
And, you are trying to assign a block to an identifier, which is an illegal
construct in C.  Anything sorrounded by parantheses is an expression, and that 
sorrounded by braces is a block(compound statement).

GCC, as an extension, allows a compound statement enclosed in parantheses as
an expression.  The value of the last statement serves as the value of the
entire construct.  So, the macro could be rewritten as:

#define STA1(t1) ({ A *p; \
                    p=t1; \
                    (p)?((int)&(p->b)):(0);  })


If it is required that only the macro should be used to get the address of 
a structure member, then following macro could be used more portably than
the above one.  Using a macro could be due to future changes and/or portability
issues.


    #include   /* for offsetof() macro */ 
    #define  STA1(ptr, member)  (ptr + offsetof ( struct A, member ))

The other undefined behaviour that can be observed is the assignment:

    k = STA1 ( &test );

assuming that the macro, STA1, evaluates to a pointer of type struct A.
The conversion from pointer to integer is implementation-defined and may
not give the results you expect.  

>     printf ( "%d\n", k );
> }

To print the value of a pointer, use the "%p" conversion specifier.
The value of the pointer is converted to a sequence of printing characters, 
in an implementation-defined manner.  The pointer should be casted to a 
pointer to void.  For example,

    struct A *ptr = STA1 ( &test );
    printf ( "%p\n", (void *) ptr );


C99 also makes available a new integer type, intptr_t, that is capable of 
holding object pointers.  The pointer should always be converted to void * 
prior the assignment.  So, for example,

    #include  /* for intptr_t */
    intptr_t ptr = (void *) STA1 ( &test );

Well, the easiest method I can think of finding the address of a structure
member, say b, is:

    printf ( "%p\n", (void *) &test -> b );

    Source: geocities.com/vijoeyz/faq/c

               ( geocities.com/vijoeyz/faq)                   ( geocities.com/vijoeyz)