Deep question for the REAL C GURU's out there ...

Roger Oberholtzer roger
Wed Feb 23 16:27:45 PST 2005


On Wed, 2005-02-23 at 10:11 -0600, Ben Duncan wrote:
> Ok, have been slag'ing away ( ;-> ) on my project.
> Done a LOT of reading of other's C projects and AM always getting tripped
> up by there usage of  structptr1->structptr2->myitem.
> 
> Now, IS this not where a structure contains another structure and the above
> is pointing to the sub-structure inside the main structure?
> 
> Now given that this is how I see everone else doing things and given the below
> code: (see rest of email following code)

The ->/. syntax is rather straight forward. And very flexible. Combine
this with the fact that the name of a array when used without an index
(without a [x]) can be used as a pointer anf you can make unusual code
'till the cows come home.

Real answer is at end of mail, but I felt I had to do a:

/Cruel_to_be_kind_mode (C code clarity is a sore point with me - sorry)

Does your code compile?

When reviewing your code, it is hard to see what is what in the
structures. Your typedefs followed by the actual structs is a 'unique'
style. Declaring the variables with the 'typedef' but declaring the
variables without it is surprising. 

I think the more traditional declarations might be as follows. I took
away the name after the 'struct' as you are not using them. They are
only useful if the typedef needs to refer to itself.

typedef struct {

     int ms_counter ;
     int ms_users ;
     char ms_status ;
     char ms_message [ 80 ] ;

} menustat;

typedef struct {

     int  mli_lineid ;
     char mli_displayname [ 16 ] ;
     char mli_type [ 8 ] ;
     char mli_program [ 24 ] ;

} menulineitem;

typedef struct {

     char menu_heading [ 12 ] ;     /* Also used as Menu ID */
     int menu_item_count ;          /* How many Line items ? */
     menulineitem menusetlineitem [ 18 ] ;
     menustat menuset_status ;

} Menu;

Much less stuff and each typedef declared in one instead of two
statements. Then your variable declarations are ok. 

You can also just ignore this and please take no offense. I just can't
resist. My problem, really.

> 
> -------------------------------------------------------------------------------
> /* C code snippet */
> 
> typedef struct Menu_Set Menu ;
> typedef struct menu_line_item menulineitem ;
> typedef struct Menu_Status menustat ;
> 
> struct Menu_Status
> {
>      int ms_counter ;
>      int ms_users ;
>      char ms_status ;
>      char ms_message [ 80 ] ;
> }
> 
> struct menu_line_item
> {
>      int  mli_lineid ;
>      char mli_displayname [ 16 ] ;
>      char mli_type [ 8 ] ;
>      char mli_program [ 24 ] ;
> 
> }  ;
> 
> struct Menu_Set
> {
>      char menu_heading [ 12 ] ;     /* Also used as Menu ID */
>      int menu_item_count ;          /* How many Line items ? */
>      menulineitem menusetlineitem [ 18 ] ;
>      menustat menuset_status ;
> }  ;
> 
> Menu menuStack[64];  /* We can have 64 menu's per system */
> Menu *menuptr;       /* Pointer to the MenuStack */
> Menu *currentMenu ;  /* Pointer to WHICH is current */
> menustat *MenuStatus /* pointer to Menu Status stuff */
> menulineitem *MenuItem;  /* Pointer to the menulineitem */
> int active_menu ;    /* COunter of active menu's set up */
> 
> ------------------------------------------------------------------------------
> int idx, midx ;
> 
> for ( midx = 0 ; midx < active_menu ; midx++
> {
> 
> /* < -- Start of PFM maybe ? */
>   menuptr = &menuStack[midx];
>   MenuStatus = &menuptr->menuset_status ;
> 
> /* Ok, watch WHAT I do here .... */
>   MenuStatus->ms_counter = 0 ;
> 
>   for ( idx = 0; idx < menuptr->menu_item_count; idx++, mrows++ )
>          {
> 
> /*   PAY CLOSE ATTENTION TO THE BELOW MenuItem CODE !!!!!!!! */
> 
>            MenuItem = &menuptr->menusetlineitem[idx];  /* <---- LOOK CLOSELY !!! */
>            MenuStatus->ms_counter++ ; /* Again, is this trickery? */
> 
>            if ( strcmp ( MenuItem->mli_type, HLINETYPE ) == 0 )
>              {
>                SLsmg_gotorc ( mrows, mcols );
>                SLsmg_set_color ( COLORSET_MENULINES );
>                SLsmg_draw_hline ( 16 );
> 
>                ............ or do other processing here ....
>                ............ with if / elses's ............
>              .....
> 
>            }  /* WRAP UP Inside for
>    } /* Wrap up outside for */
> 
> ------------------------------------------------------------------------------
> 
> 
> Notice the MenuStatus and the MenuItem pointers. I can set these to directly to the
> address of the information I need to access. And they WORK as should ( I have tested
> this out).
> 
> Now my questions's are:
> 
> If this works, why does everone use the "aptr->bptr->item" method. Is that more the 
> political correct method? Is there anything BAD or BORKEN with doing the way I am doing it?

I don't think everyone does this. I do lots of embedded real time DSP
programming in C. Although the Texas Instruments (for the DSPs we use)
compiler has improved in recent years, not so very long ago you had to
make pointers to such structures so that variable access is better. Or
not use structures...

Such access is not bad or broken. You can always make a variable be a
pointer to anything in a structure. And using data structures makes all
this easier. This use of pointers is what makes C so powerful - and so
easy to abuse.

Modern compilers sense these sorts of things and may internally make a
variable (or register) for this access. But if you brute force it there
is no trouble.

> Is this going to be the same nightmare I faced 30 some odd years ago when I learned COBOL -
> that there are so many ways to do things, you just have to pick a method and live with it?

Yes and no. If you are only going to access the nested data a very few
times, then making a variable is perhaps overkill. But by using your
data structures like this, you can make more modular code. Data in a
large data structure need not be handled by large amounts of C code.
Break the data up into meaningful/logical chunks and make code that just
knows about that part of the data, and you will make better code.

Towards that end, be sure to explore the 'static inline' type of C
function. Hint hint.


-- 
Roger Oberholtzer <roger at opq.se>



More information about the Linux-users mailing list