RPM Community Forums

Mailing List Message of <rpm-devel>

Re: Cast for a union C question.

From: Jeff Johnson <n3npq@mac.com>
Date: Wed 17 Oct 2007 - 23:56:13 CEST
Message-Id: <1C4D7F84-7ECF-4D5E-9E02-DF4DCF307A43@mac.com>

On Oct 17, 2007, at 1:08 PM, Ralf S. Engelschall wrote:

> On Wed, Oct 17, 2007, Jeff Johnson wrote:
>
>> I'm in the last stages of establishing a typedef for
>> data returned from headerGetEntry() et al methods.
>>
>> Since the data is typed, a union is being used:
>> union hRET_s {
>>    void * ptr;
>>    const char ** argv;
>>    const char * str;
>>    uint_64 * ui64p;
>>    uint_32 * ui32p;
>>    uint_16 * ui16p;
>>    uint_8 * ui8p;
>>    int_64 * i64p;
>>    int_32 * i32p;
>>    int_16 * i16p;
>>    int_8 * i8p;
>> };
>> typedef union hRET_s rpmTagData;
>>
>> Since the current API uses "const void *", there is a need to
>> convert the void * to a union pointer at the moment. I'll fight the
>>    You changed rpmlib's API!
>> issues after all the work is actually done.
>>
>> Well I'm baffled by how to achieve the cast. Everything I've tried  
>> with
>> casts fails to compile.
>>
>> This hackery with an extra level of indirection manages to change
>> the pointer type, but is perhaps overkill:
>>
>> int headerAddEntry(Header h, int_32 tag, rpmTagType type,
>>                const void * p, rpmTagCount c)
>>        /*@modifies h @*/
>> {
>>    rpmTagData *q = (void *)&p;
>>    return (h2hv(h)->hdradd) (h, tag, type, *q, c);
>> }
>>
>> So how does one achieve casting from void * to a union?
>>
>> Inquiring minds want to know ...
>
> Why is there "(void *)&p"? I would have expected just "(void *)p" or
> even "(rpmTagData *)p". Also, you are passing "*q" to the function  
> which
> would mean that the union is passed by value, right? Is this really  
> what
> you want? Why not pass-though just the pointer to the union?
>

I used
     rpmTagData *q = (void *)&p;
and then later
     ..., *q, ...

Turned out I had written
    typedef const hRET_t rpmTagData;
Note the "const".

Once I figgered the sloppiness, casts for unions started to behave ;-)

Still, union ptrs are a bit bizzare, e.g.
     (*he->p).str = "some string"
rather than the (more natural to me, not C ;-)
     *he->p.str = "some string";

There's still 1 level of indirection I need to eliminate
to push rpmTagData back into a HE_t.

And enum typedef's are kinda wonky too. E.g.
     typedef enum rpmTag_e rpmTag;
     ...
     rpmTag foo;
won't "work" unless enum rpmTag_e is known when typedef is 1st used.

Ah well, I'm just a carpenter, not a pedant. ptrs is ptrs and ints is  
ints, that's
all I really need to hammer out a solution.

Still, getting rpmTagFoo private typedefs means gcc is actually helping
find coding problems, that's already a win.

Anyone for bit fields? There's actually a need for arbitrary named bits
in tags with
    Requires(foo): ....

73 de Jeff
Received on Wed Oct 17 23:57:22 2007
Driven by Jeff Johnson and the RPM project team.
Hosted by OpenPKG and Ralf S. Engelschall.
Powered by FreeBSD and OpenPKG.