Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #75010 > unrolled thread

Question about type cast in queue code

Started byfl <rxjwg98@gmail.com>
First post2015-11-05 12:21 -0800
Last post2015-12-06 15:31 -0800
Articles 16 — 7 participants

Back to article view | Back to comp.lang.c


Contents

  Question about type cast in queue code fl <rxjwg98@gmail.com> - 2015-11-05 12:21 -0800
    Re: Question about type cast in queue code Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-11-05 20:43 +0000
    Re: Question about type cast in queue code James Kuyper <jameskuyper@verizon.net> - 2015-11-05 16:10 -0500
      Re: Question about type cast in queue code fl <rxjwg98@gmail.com> - 2015-11-05 16:50 -0800
        Re: Question about type cast in queue code James Kuyper <jameskuyper@verizon.net> - 2015-11-05 21:37 -0500
          Re: Question about type cast in queue code Philip Lantz <prl@canterey.us> - 2015-11-06 20:37 -0800
            Re: Question about type cast in queue code James Kuyper <jameskuyper@verizon.net> - 2015-11-07 00:20 -0500
              Re: Question about type cast in queue code Philip Lantz <prl@canterey.us> - 2015-11-07 11:51 -0800
                Re: Question about type cast in queue code James Kuyper <jameskuyper@verizon.net> - 2015-11-07 15:34 -0500
                  Re: Question about type cast in queue code Philip Lantz <prl@canterey.us> - 2015-11-07 13:42 -0800
                    Re: Question about type cast in queue code James Kuyper <jameskuyper@verizon.net> - 2015-11-07 16:53 -0500
            Re: Question about type cast in queue code David Thompson <dave.thompson2@verizon.net> - 2015-12-06 07:56 -0500
              Re: Question about type cast in queue code Keith Thompson <kst-u@mib.org> - 2015-12-06 12:28 -0800
                Re: Question about type cast in queue code Philip Lantz <prl@canterey.us> - 2015-12-06 13:29 -0800
          Re: Question about type cast in queue code James Kuyper <jameskuyper@verizon.net> - 2015-12-06 18:18 -0500
            Re: Question about type cast in queue code supercat@casperkitty.com - 2015-12-06 15:31 -0800

#75010 — Question about type cast in queue code

Fromfl <rxjwg98@gmail.com>
Date2015-11-05 12:21 -0800
SubjectQuestion about type cast in queue code
Message-ID<b3348687-a459-4ebc-89fe-5ff59f4bd55b@googlegroups.com>
Hi,

I try to write a queue application on Tiva-C 1294 board. I find the following line is difficult to understand:

elem != (Queue_Elem *)myQ; 

myQ is a Queue_Handletype variable. Type cast (Queue_Elem *) does make it work. But I feel it is beyond of my understanding now.
Why and how does the type cast work for this?



Thanks,



/* This structure can be added to a Queue because the first field is a Queue_Elem. */
typedef struct Rec {
Queue_Elem elem;
Int data;
} Rec;
Queue_Handle myQ;
...

Queue_Elem *elem;
for (elem = Queue_head(myQ); elem != (Queue_Elem *)myQ;
elem = Queue_next(elem)) {
...
}





[toc] | [next] | [standalone]


#75014

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2015-11-05 20:43 +0000
Message-ID<87io5gyy77.fsf@bsb.me.uk>
In reply to#75010
fl <rxjwg98@gmail.com> writes:
<snip>
> /* This structure can be added to a Queue because the first field is a
> Queue_Elem. */
> typedef struct Rec {
> Queue_Elem elem;
> Int data;
> } Rec;

This is a common technique to allow structures like lists and queues to
hold arbitrary user-defined data.  Unfortunately I don't know if it has
a common name you can use to search for examples.

> Queue_Handle myQ;
> ...
>
> Queue_Elem *elem;
> for (elem = Queue_head(myQ); elem != (Queue_Elem *)myQ;
> elem = Queue_next(elem)) {
> ...
> }

Unfortunately you don't show the definition of the type Queue_Handle so
it's hard to know what relation is has with a Queue_Elem.  If you are
using the same included struct trick that Rec uses, the test you
want is probably

  else != &myO.elem

but that is no more than a wild guess right now.

If possible, post a complete program or at least post the definitions of
all the types, variable and so on that are referred to.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#75020

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-05 16:10 -0500
Message-ID<n1ggg3$ag8$1@dont-email.me>
In reply to#75010
On 11/05/2015 03:21 PM, fl wrote:
> Hi,
> 
> I try to write a queue application on Tiva-C 1294 board. I find the following line is difficult to understand:
> 
> elem != (Queue_Elem *)myQ; 
> 
> myQ is a Queue_Handletype variable. Type cast (Queue_Elem *) does make it work. But I feel it is beyond of my understanding now.
> Why and how does the type cast work for this?

The code you've provided is insufficient to answer that question. At a
minimum, we need to know the definition of the Queue_Handle type, and
knowing the definition of the Queue_Elem type might also be useful.

It would also help if you could articulate better what feature of this
code makes it hard for you to understand. One way to approach that
question is to give us an example of similar code that you do
understand; the difference between the code you do understand and the
code you don't understand could give us some clue as to what it is that
is giving you trouble understanding it.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#75036

Fromfl <rxjwg98@gmail.com>
Date2015-11-05 16:50 -0800
Message-ID<8c81e1b0-cd60-44a9-8d48-21b266a97ce9@googlegroups.com>
In reply to#75020
On Thursday, November 5, 2015 at 4:10:42 PM UTC-5, James Kuyper wrote:
> On 11/05/2015 03:21 PM, fl wrote:
> > Hi,
> > 
> > I try to write a queue application on Tiva-C 1294 board. I find the following line is difficult to understand:
> > 
> > elem != (Queue_Elem *)myQ; 
> > 
> > myQ is a Queue_Handletype variable. Type cast (Queue_Elem *) does make it work. But I feel it is beyond of my understanding now.
> > Why and how does the type cast work for this?
> 
> The code you've provided is insufficient to answer that question. At a
> minimum, we need to know the definition of the Queue_Handle type, and
> knowing the definition of the Queue_Elem type might also be useful.
> 
> It would also help if you could articulate better what feature of this
> code makes it hard for you to understand. One way to approach that
> question is to give us an example of similar code that you do
> understand; the difference between the code you do understand and the
> code you don't understand could give us some clue as to what it is that
> is giving you trouble understanding it.
> -- 
> James Kuyper

Thanks for the replies. Due to the complexities of the project, there is not 
a clearly definition of the Queue_Elem. But I think its description, see
 below could help. My understanding difficulties are in the conversion of
 handler 'myQ' to type 'Queue_Elem':

elem != (Queue_Elem *)myQ;

After I think a while of the type definition 'Rec', I guess that 
'Queue_Elem _elem;' is the first element of the struct is crucial. This 
arrangement makes the address of 'Queue_Elem' and Rec pointer (such as rp)
 is the same.

Change the struct definition to:

typedef struct Rec {
      Int data;
      Queue_Elem _elem;
  } Rec;

will invalidate the original type casting:

elem != (Queue_Elem *)myQ;

Am I right? 
Thanks,
........
The Queue module makes available a set of functions that manipulate queue objects accessed through handles of type Queue_Handle. Each queue contains a linked sequence of zero or more elements referenced through variables of type Queue_Elem, which are embedded as the first field within a structure.

In the Queue API descriptions, the APIs which disable interrupts before modifying the Queue are noted as "atomic", while APIs that do not disable interrupts are "non-atomic".

Queues are represented as doubly-linked lists, so calls to Queue_next or Queue_prev can loop continuously over the Queue. The following code demonstrates one way to iterate over a Queue once from beginning to end. In this example, 'myQ' is a Queue_Handle.

  Queue_Elem *elem;

  for (elem = Queue_head(myQ); 
      elem != (Queue_Elem *)myQ; 
      elem = Queue_next(elem)) {
      ...
  }


Below is a simple example of how to create a Queue, enqueue two elements, and dequeue the elements until the queue is empty:

  #include <xdc/std.h>
  #include <xdc/runtime/System.h>
  
  #include <../knl/Queue.h>
  
  typedef struct Rec {
      Queue_Elem _elem;
      Int data;
  } Rec;
  
  Int main(Int argc, Char *argv[])
  {
      Queue_Handle q;
      Rec r1, r2;
      Rec* rp;
  
      r1.data = 100;
      r2.data = 200;
  
  
      // create a Queue instance 'q'
      q = Queue_create(NULL, NULL);
  
  
      // enQ a couple of records
      Queue_enqueue(q, &r1._elem);
      Queue_enqueue(q, &r2._elem);
  
  
      // deQ the records and print their data values until Q is empty
      while (!Queue_empty(q)) {
          rp = Queue_dequeue(q);
          System_printf("rec: %d\n", rp->data);
      }
  
      System_exit(0);
      return (0);
  }

[toc] | [prev] | [next] | [standalone]


#75042

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-05 21:37 -0500
Message-ID<n1h3lu$6t1$1@dont-email.me>
In reply to#75036
On 11/05/2015 07:50 PM, fl wrote:
> On Thursday, November 5, 2015 at 4:10:42 PM UTC-5, James Kuyper wrote:
>> On 11/05/2015 03:21 PM, fl wrote:
>>> Hi,
>>>
>>> I try to write a queue application on Tiva-C 1294 board. I find the following line is difficult to understand:
>>>
>>> elem != (Queue_Elem *)myQ; 
>>>
>>> myQ is a Queue_Handletype variable. Type cast (Queue_Elem *) does make it work. But I feel it is beyond of my understanding now.
>>> Why and how does the type cast work for this?
>>
>> The code you've provided is insufficient to answer that question. At a
>> minimum, we need to know the definition of the Queue_Handle type, and
>> knowing the definition of the Queue_Elem type might also be useful.
>>
>> It would also help if you could articulate better what feature of this
>> code makes it hard for you to understand. One way to approach that
>> question is to give us an example of similar code that you do
>> understand; the difference between the code you do understand and the
>> code you don't understand could give us some clue as to what it is that
>> is giving you trouble understanding it.
>> -- 
>> James Kuyper
> 
> Thanks for the replies. Due to the complexities of the project, there is not 
> a clearly definition of the Queue_Elem.

That is simply impossible. You might not be clear about the definition
of Queue_Elem, but C compilers don't tolerate unclear definitions.
Somewhere in the source code is a precise, perfectly clear definition
for Queue_Elem, or code that uses Queue_Elem wouldn't be able to
compile. You've just got to find out where that definition is.

In any event, Queue_Elem is less important than Queue_Handle. Without a
definition for Queue_Handle, it's impossible to make any meaningful
comments addressing your question. Can you locate that definition?

...
>   #include <xdc/std.h>
>   #include <xdc/runtime/System.h>
>   
>   #include <../knl/Queue.h>

It seems likely that you'll be able to find the definition for
Queue_Handle in that header file.

If you can't find the header file, there's another approach that might
work. Many compilers have an option to produce pre-processed output
only. For instance, for gcc the relevant option is -E. If you could
create a program file that contains only the above #include statement,
and then process it with gcc -E, the output should contain a definition
for Queue_Handle.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#75213

FromPhilip Lantz <prl@canterey.us>
Date2015-11-06 20:37 -0800
Message-ID<MPG.30a71fd29d392c1b84@news.eternal-september.org>
In reply to#75042
James Kuyper wrote:
> 
> fl wrote:
> > Thanks for the replies. Due to the complexities of the project, there 
> > is not a clearly definition of the Queue_Elem.
> 
> That is simply impossible. You might not be clear about the definition
> of Queue_Elem, but C compilers don't tolerate unclear definitions.
> Somewhere in the source code is a precise, perfectly clear definition
> for Queue_Elem, or code that uses Queue_Elem wouldn't be able to
> compile. You've just got to find out where that definition is.

I usually try to avoid picking nits, but I have to throw this at you:

struct Queue_Elem;

int main()
{
    Queue_Elem *elem = 0;
    void *myQ = 0;

    elem != (Queue_Elem *)myQ;

    return 0;
}

:-)

[toc] | [prev] | [next] | [standalone]


#75215

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-07 00:20 -0500
Message-ID<n1k1jb$t4a$1@dont-email.me>
In reply to#75213
On 11/06/2015 11:37 PM, Philip Lantz wrote:
> James Kuyper wrote:
>>
>> fl wrote:
>>> Thanks for the replies. Due to the complexities of the project, there 
>>> is not a clearly definition of the Queue_Elem.
>>
>> That is simply impossible. You might not be clear about the definition
>> of Queue_Elem, but C compilers don't tolerate unclear definitions.
>> Somewhere in the source code is a precise, perfectly clear definition
>> for Queue_Elem, or code that uses Queue_Elem wouldn't be able to
>> compile. You've just got to find out where that definition is.
> 
> I usually try to avoid picking nits, but I have to throw this at you:
> 
> struct Queue_Elem;
> 
> int main()
> {
>     Queue_Elem *elem = 0;
>     void *myQ = 0;
> 
>     elem != (Queue_Elem *)myQ;
> 
>     return 0;
> }

You're right - it's possible to write code using pointers to structs,
without having a definition of the struct type itself. But while that
might be precisely what's going on inside fl's code, his code calls
routines named Queue_head(), Queue_next(), Queue_create() and
Queue_enqueue(). At least one of those routines must know the definition
of Queue_Handle, and without that definition, I can't answer fl's question.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#75287

FromPhilip Lantz <prl@canterey.us>
Date2015-11-07 11:51 -0800
Message-ID<MPG.30a7f6206a9f01358b@news.eternal-september.org>
In reply to#75215
James Kuyper wrote:
> Philip Lantz wrote:
> > James Kuyper wrote:
> >>
> >> fl wrote:
> >>> Thanks for the replies. Due to the complexities of the project, there 
> >>> is not a clearly definition of the Queue_Elem.
> >>
> >> That is simply impossible. You might not be clear about the definition
> >> of Queue_Elem, but C compilers don't tolerate unclear definitions.
> >> Somewhere in the source code is a precise, perfectly clear definition
> >> for Queue_Elem, or code that uses Queue_Elem wouldn't be able to
> >> compile. You've just got to find out where that definition is.
> > 
> > I usually try to avoid picking nits, but I have to throw this at you:
> > 
> > struct Queue_Elem;
> > 
> > int main()
> > {
> >     Queue_Elem *elem = 0;
> >     void *myQ = 0;
> > 
> >     elem != (Queue_Elem *)myQ;
> > 
> >     return 0;
> > }
> 
> You're right - it's possible to write code using pointers to structs,
> without having a definition of the struct type itself. But while that
> might be precisely what's going on inside fl's code, his code calls
> routines named Queue_head(), Queue_next(), Queue_create() and
> Queue_enqueue(). At least one of those routines must know the definition
> of Queue_Handle ...

We were talking about Queue_Elem, not Queue_Handle. None of those
routines need to know the definition of Queue_Elem; it could be a
completely abstract type, intended only for the user of the queue
code, and which is cast to a concrete type inside the queue functions
whenever it is used.

Or, the queue functions could be in a library, the source of which he
has no access to.

(I'm only picking on the words "simply impossible." If you had said
"unlikely", I wouldn't have said anything.)

Philip

[toc] | [prev] | [next] | [standalone]


#75293

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-07 15:34 -0500
Message-ID<563E6039.5000606@verizon.net>
In reply to#75287
On 11/07/2015 02:51 PM, Philip Lantz wrote:
> James Kuyper wrote:
>> Philip Lantz wrote:
>>> James Kuyper wrote:
>>>>
>>>> fl wrote:
>>>>> Thanks for the replies. Due to the complexities of the project, there 
>>>>> is not a clearly definition of the Queue_Elem.
>>>>
>>>> That is simply impossible. You might not be clear about the definition
>>>> of Queue_Elem, but C compilers don't tolerate unclear definitions.
>>>> Somewhere in the source code is a precise, perfectly clear definition
>>>> for Queue_Elem, or code that uses Queue_Elem wouldn't be able to
>>>> compile. You've just got to find out where that definition is.
>>>
>>> I usually try to avoid picking nits, but I have to throw this at you:
>>>
>>> struct Queue_Elem;
>>>
>>> int main()
>>> {
>>>     Queue_Elem *elem = 0;
>>>     void *myQ = 0;
>>>
>>>     elem != (Queue_Elem *)myQ;
>>>
>>>     return 0;
>>> }
>>
>> You're right - it's possible to write code using pointers to structs,
>> without having a definition of the struct type itself. But while that
>> might be precisely what's going on inside fl's code, his code calls
>> routines named Queue_head(), Queue_next(), Queue_create() and
>> Queue_enqueue(). At least one of those routines must know the definition
>> of Queue_Handle ...
> 
> We were talking about Queue_Elem, not Queue_Handle.

Feel free to talk about something else if you wish, but whenever I have
mentioned Queue_Handle, I did so because I was in fact talking about
Queue_Handle, not Queue_Elem. I talked about Queue_Elem only because fl
ignored my main question, which was about the definition of
Queue_Handle, and instead gave a non-answer to my secondary question
about the definition of Queue_Elem.

fl said that Queue_Handle was the type of myQ, and it is therefore a
type whose definition is relevant to the answer of his question. In
particular, if Queue_Handle is a pointer to a struct whose first member
has the type Queue_Elem, then I don't need to know anything more about
the meaning of Queue_Elem in order to answer his question. It works the
other way, too: if Queue_Elem is a struct type, and the first member of
that struct has the same type that Queue_Handle points at, I can also
explain how the code is working, and I don't need to know anything more
about the type that Queue_Handle points at. If Queue_Elem has character
type, or if Queue_Handle points at a character type, I can also explain
it. However, I can't choose the correct explanation until fl tells me
what the relevant definitions are.

> None of those
> routines need to know the definition of Queue_Elem; it could be a
> completely abstract type, intended only for the user of the queue
> code, and which is cast to a concrete type inside the queue functions
> whenever it is used.

In order to perform that cast, those functions need to know what that
concrete type is.

> Or, the queue functions could be in a library, the source of which he
> has no access to.

True. However, that inaccessible source code must know what the
definition of that type is. That code might be in a language other than
C, and might therefore define the type using different syntax than C
uses. It might not even be a named type; the definition would simply be
implicit in the instructions used to access the value of the
corresponding object - but that code must know that definition.

[toc] | [prev] | [next] | [standalone]


#75297

FromPhilip Lantz <prl@canterey.us>
Date2015-11-07 13:42 -0800
Message-ID<MPG.30a81022299def368e@news.eternal-september.org>
In reply to#75293
James Kuyper wrote:
> 
> On 11/07/2015 02:51 PM, Philip Lantz wrote:
> > James Kuyper wrote:
> >> Philip Lantz wrote:
> >>> James Kuyper wrote:
> >>>>
> >>>> fl wrote:
> >>>>> Thanks for the replies. Due to the complexities of the project, there 
> >>>>> is not a clearly definition of the Queue_Elem.
> >>>>
> >>>> That is simply impossible. You might not be clear about the definition
> >>>> of Queue_Elem, but C compilers don't tolerate unclear definitions.
> >>>> Somewhere in the source code is a precise, perfectly clear definition
> >>>> for Queue_Elem, or code that uses Queue_Elem wouldn't be able to
> >>>> compile. You've just got to find out where that definition is.
> >>>
> >>> I usually try to avoid picking nits, but I have to throw this at you:
> >>>
> >>> struct Queue_Elem;
> >>>
> >>> int main()
> >>> {
> >>>     Queue_Elem *elem = 0;
> >>>     void *myQ = 0;
> >>>
> >>>     elem != (Queue_Elem *)myQ;
> >>>
> >>>     return 0;
> >>> }
> >>
> >> You're right - it's possible to write code using pointers to structs,
> >> without having a definition of the struct type itself. But while that
> >> might be precisely what's going on inside fl's code, his code calls
> >> routines named Queue_head(), Queue_next(), Queue_create() and
> >> Queue_enqueue(). At least one of those routines must know the definition
> >> of Queue_Handle ...
> > 
> > We were talking about Queue_Elem, not Queue_Handle.
> 
> Feel free to talk about something else if you wish, but whenever I have
> mentioned Queue_Handle, I did so because I was in fact talking about
> Queue_Handle, not Queue_Elem.

It's right there in the quotes above, but I'll quote it again:
> >>> James Kuyper wrote:
> >>>> fl wrote:
> >>>>> Thanks for the replies. Due to the complexities of the project, there 
> >>>>> is not a clearly definition of the Queue_Elem.
> >>>>
> >>>> That is simply impossible.

That is the *only* part of this thread that I have been responding to.

And I acknowledged that it is a nit (and hence off the main point), right
in my original comment. (Also shown in the quotes above.)

[toc] | [prev] | [next] | [standalone]


#75299

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-11-07 16:53 -0500
Message-ID<563E72DC.6080204@verizon.net>
In reply to#75297
On 11/07/2015 04:42 PM, Philip Lantz wrote:
> James Kuyper wrote:
>>
>> On 11/07/2015 02:51 PM, Philip Lantz wrote:
....
>>> We were talking about Queue_Elem, not Queue_Handle.
>>
>> Feel free to talk about something else if you wish, but whenever I have
>> mentioned Queue_Handle, I did so because I was in fact talking about
>> Queue_Handle, not Queue_Elem.
> 
> It's right there in the quotes above, but I'll quote it again:
>>>>> James Kuyper wrote:
>>>>>> fl wrote:
>>>>>>> Thanks for the replies. Due to the complexities of the project, there 
>>>>>>> is not a clearly definition of the Queue_Elem.
>>>>>>
>>>>>> That is simply impossible.
> 
> That is the *only* part of this thread that I have been responding to.

Perhaps - but it's not the only part of this thread I was talking about
when answering your responses. The fact that some part of the code must
know the definition of Queue_Handle is very relevant to what I was
talking about, however irrelevant it might have been to what you were
talking about.
Also, what you were saying about Queue_Elem was, as far as I can tell,
equally true about the type that Queue_Handle points at (assuming that
it is a pointer type rather than an integer type), so I don't really see
the point in your decision to restrict your own comments to Queue_Elem.

[toc] | [prev] | [next] | [standalone]


#77969

FromDavid Thompson <dave.thompson2@verizon.net>
Date2015-12-06 07:56 -0500
Message-ID<d3c86bhci7p71v54e9ujpnq7cvt9f2k81g@4ax.com>
In reply to#75213
On Fri, 6 Nov 2015 20:37:10 -0800, Philip Lantz <prl@canterey.us>
wrote:

> James Kuyper wrote:
> > 
> > fl wrote:
> > > Thanks for the replies. Due to the complexities of the project, there 
> > > is not a clearly definition of the Queue_Elem.
> > 
> > That is simply impossible. You might not be clear about the definition
> > of Queue_Elem, but [it's there somewhere]
> 
> I usually try to avoid picking nits, but I have to throw this at you:
> 
> struct Queue_Elem;
> 
> int main()
> {
>     Queue_Elem *elem = 0;
>     void *myQ = 0;
> 
>     elem != (Queue_Elem *)myQ;
> 
>     return 0;
> }
> 
As long as we're nitpicking, in C you need something like 

typedef struct new_tag_name Queue_Elem;
/* new_tag_name MAY be Queue_Elem but need not */

In C++ a tag works almost like a typedef. Not C.

[toc] | [prev] | [next] | [standalone]


#77996

FromKeith Thompson <kst-u@mib.org>
Date2015-12-06 12:28 -0800
Message-ID<lnd1ujpbi5.fsf@kst-u.example.com>
In reply to#77969
David Thompson <dave.thompson2@verizon.net> writes:
> On Fri, 6 Nov 2015 20:37:10 -0800, Philip Lantz <prl@canterey.us>
> wrote:
[...]
>> struct Queue_Elem;
>> 
>> int main()
>> {
>>     Queue_Elem *elem = 0;
>>     void *myQ = 0;
>> 
>>     elem != (Queue_Elem *)myQ;
>> 
>>     return 0;
>> }
>> 
> As long as we're nitpicking, in C you need something like 
>
> typedef struct new_tag_name Queue_Elem;
> /* new_tag_name MAY be Queue_Elem but need not */

No, you don't *need* a typedef.  You can just refer to the type by
its original name, which happens to be `struct Queue_Elem`.  Using a
typedef to give it a new name `Queue_Elem` is entirely optional.

> In C++ a tag works almost like a typedef. Not C.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#78000

FromPhilip Lantz <prl@canterey.us>
Date2015-12-06 13:29 -0800
Message-ID<MPG.30ce487630a1944abf@news.eternal-september.org>
In reply to#77996
Keith Thompson wrote:
> David Thompson writes:
> > On Fri, 6 Nov 2015 20:37:10 -0800, Philip Lantz wrote:
> >> struct Queue_Elem;
> >> 
> >> int main()
> >> {
> >>     Queue_Elem *elem = 0;
> >>     void *myQ = 0;
> >> 
> >>     elem != (Queue_Elem *)myQ;
> >> 
> >>     return 0;
> >> }
> >> 
> > As long as we're nitpicking, in C you need something like 
> >
> > typedef struct new_tag_name Queue_Elem;
> > /* new_tag_name MAY be Queue_Elem but need not */
> 
> No, you don't *need* a typedef.  You can just refer to the type by
> its original name, which happens to be `struct Queue_Elem`.

Yes, that's what I intended to write. I've been writing so
much C++ lately that I overlooked it.

[toc] | [prev] | [next] | [standalone]


#78009

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-12-06 18:18 -0500
Message-ID<5664C24E.7050204@verizon.net>
In reply to#75042
James Kuyper wrote:
> 
> fl wrote:
> > Thanks for the replies. Due to the complexities of the project, there 
> > is not a clearly definition of the Queue_Elem.
> 
> That is simply impossible. You might not be clear about the definition
> of Queue_Elem, but C compilers don't tolerate unclear definitions.
> Somewhere in the source code is a precise, perfectly clear definition
> for Queue_Elem, or code that uses Queue_Elem wouldn't be able to
> compile. You've just got to find out where that definition is.

Given the recently renewed interest in this thread, I decided to go
looking to see if I could find the definitions that fl claimed are
unavailable. A Google search brought me to >
<http://software-dl.ti.com/dsps/dsps_public_sw/sdo_sb/targetcontent/sysbios/6_40_04_47/exports/bios_6_40_04_47/docs/cdoc/ti/sysbios/knl/Queue.html#xdoc-desc>.

I've no idea whether that's relevant - the names are sufficiently
generic that it's possible, though unlikely, that fl was using some
other library that uses the same names. ti.com is a domain name where I
can also find references to the Tiva-C 1294 board that fl referred to,
but I did not manage to find a direct connection between the Tiva-C 1294
and the URL I gave above. Possibly I didn't look hard enough.

Unless and until fl chooses to enlighten us otherwise, I'll go ahead on
the assumption that this documentation is relevant. If it isn't, my
analysis of this documentation will at least provide a model that fl can
use to analyze the correct documentation.

The only items from that page needed to deal with fl's question are:

> typedef struct Queue_Elem {
>     Queue_Elem *next;
>     Queue_Elem *prev;
> } Queue_Elem;

and

> typedef struct Queue_Object Queue_Object;
> // Opaque internal representation of an instance object
>  
> typedef Queue_Object *Queue_Handle;
> // Client reference to an instance object


fl's original question was:
> I try to write a queue application on Tiva-C 1294 board. I find the following line is difficult to understand:
> 
> elem != (Queue_Elem *)myQ;
> 
> myQ is a Queue_Handletype variable. Type cast (Queue_Elem *) does make it work. But I feel it is beyond of my understanding now.
> Why and how does the type cast work for this? 

Replacing typedefs with their original types, this becomes:

    struct Queue_Object *myQ;

and

    elem != (struct Queue_Elem*)myQ;

Now, since struct Queue_Object is an opaque type, it's not possible to
be certain whether this code has well-defined behavior. If we assume
that myQ is correctly aligned to allow conversion to struct Queue_Elem*,
then 6.3.2.3p7 guarantees that (struct Queue_Object*)elem == myQ.
However, it seem likely that this conversion was performed for reasons
other than simply converting it back again. More information than simply
"correct alignment" is needed to justify dereferencing elem.

What's needed is the type of the first member of struct Queue_Object. If
we assume that *elem has well-defined behavior, we can work backwards to
determine what the possible types for that member are. There are
infinitely many such types, but that infinite set is easy to
characterize; it's only infinite because the definition involves
recursion, and in real life it's unlikely that the recursion goes very
far - even one step of recursion is pretty unlikely.
The first member of a struct Queue_Object must be either a struct
Queue_Elem object, or recursively, either another struct whose first
member is of struct Queue_Elem type, or a union where any member is of
that type. If that weren't the case, the only thing you could safely do
with *elem is &*elem.

If a union is involved, then reading elem->next or elem->prev requires
that the last write to that union must have left it containing a bit
pattern that can be interpreted as a representing a valid value for the
pointer that is read. There's other ways to achieve that result, but the
simplest is if the last write used the struct Queue_Elem member of that
union (6.5.2.3p3 and footnote 95).

In that case, this code is relying upon (6.7.2.1p11): "A pointer to a
structure object, suitably converted, points to its initial member (or
if that member is a bit-field, then to the unit in which it resides),
and vice versa." and possibly upon (6.7.2.1p16) "A pointer to a union
object, suitably converted, points to each of its members (or if a
member is a bitfield, then to the unit in which it resides), and vice
versa."

Thus, the result of the conversion is that elem is now pointing at a
struct Queue_Elem object that, one way or another, occupies the very
beginning of struct Queue_Object.

Another case that should apply is if the first member is an array of
struct Queue_Elem, but there's no clause in the standard defining the
behavior of the conversions from a pointer to an array to a pointer to
it's element type. We all "know" that this is a perfectly well-defined
conversion that results in a pointer to the first element of the array
(and that the reverse conversion is also safe) - which would combine
with 6.7.2.1p11 to allow such code. However, when I've asked, repeatedly
over the years, for a citation from the standard supporting that
"knowledge", all I've gotten was silence. I can't find it. It should be
somewhere in 6.7.6.2.

[toc] | [prev] | [next] | [standalone]


#78011

Fromsupercat@casperkitty.com
Date2015-12-06 15:31 -0800
Message-ID<65ca6da5-790a-46da-868f-db6141dd68e7@googlegroups.com>
In reply to#78009
On Sunday, December 6, 2015 at 5:18:47 PM UTC-6, James Kuyper wrote:
> What's needed is the type of the first member of struct Queue_Object. If
> we assume that *elem has well-defined behavior...

Well-defined in what language?  ANSI C, or the language described by K&R 2,
which is ANSI C but with an extension that, among other things, allows a
pointer to any structure to be used as a pointer to any other structure
with the same initial sequence, provided that it is only used to access
members within that initial sequence?

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web