CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

struct pointers and the dot operator

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jeremiah



Joined: 20 Jul 2010
Posts: 1346

View user's profile Send private message

struct pointers and the dot operator
PostPosted: Sat Feb 11, 2012 5:28 pm     Reply with quote

So I am kinda stumped on how to do something from a philosophical standpoint.

I realize that pointers to structs should use the -> operator to dereference member variables. However, I accidentally found out that the dot operator can also be used with pointers to structs. Furthermore, using the dot operator can (at times) provide a much more streamlined assembly code.

So I am trying to figure out if it is worth the tradeoff of having more streamlined assembly at the cost of doing something that "shouldn't" be done. Well I assume it shouldn't be possible. It isn't legal C that I am aware of and even though CCS isn't known for being strict C, this doesn't appear to be documented in the manual.

I'm using the PIC24FJ64GA004 and the 4.129 compiler by the way.

Here is a source example to show what I mean:
Code:

#include <24FJ64GA004.h>

#DEVICE *=16

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOWINDIS                 //Watch Dog Timer in Window mode
#FUSES NOJTAG                   //JTAG disabled
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOIOL1WAY                //Allows multiple reconfigurations of peripheral pins
#FUSES NOCKSFSM                 //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES PR                       //Primary Oscillator

#use delay(clock=22118400)

typedef struct {
   unsigned int8 value;
} my_struct_type;

my_struct_type g_test;

void main()
{

   my_struct_type *m;
   
   m = &g_test;
   
   m->value = 5;
   m.value  = 5;    //shouldn't be legal but works
   
   while(TRUE);

}



Here are the assembly listings for each method:

-> Operator
Code:

....................    m->value = 5;
0218:  MOV     #0,W0
021A:  ADD     802,W0
021C:  MOV     W0,W5
021E:  MOV.B   #5,W0L
0220:  MOV.B   W0L,[W5]



. Operator
Code:

....................    m.value  = 5;
0222:  MOV.B   #5,W0L
0224:  MOV.B   W0L,802


Notice the setup for the -> operator takes 3 instuctions versus 0 for the dot operator.

Any suggestions?
andrewg



Joined: 17 Aug 2005
Posts: 316
Location: Perth, Western Australia

View user's profile Send private message Visit poster's website

PostPosted: Sun Feb 12, 2012 1:17 am     Reply with quote

I don't think there's anything philosophical about this. It's wrong and you know it's wrong. The odds are it's a bug that CCS will fix in the next version, so there's no point trying to take advantage of it.

Having said that, using struct pointers and -> does take up a lot of code space. If that's a problem, what I do is create a local copy in the function and use that:
Code:
void foo(my_struct_type *p)
{
  my_struct_type t;
  t = *p; // temp local copy
  // ... use t.value, etc ...
  *p = t; // save temp local copy
}

_________________
Andrew
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Sun Feb 12, 2012 3:05 am     Reply with quote

Andrewg is 'spot on'. It doesn't actually work anyway....

The first code, takes the offset to the required byte in the structure, and adds it to the contents of the variable stored at 802 (m). Puts this total into W5. Then puts '5' into WOL, and uses the address in W5 as an indirect pointer to store the value in WOL. Result '5' gets put into address 800.
The second code just takes ''5' and writes it directly into 'm' at 802. So the value replaces the address stored here. Not equivalent at all.

In fact the code generated by CCS is perfectly 'correct' for both syntaxes.
The -> form says 'use the value stored in this register as a pointer, and write the value given to the address defined by this pointer, plus the 'offset' to the required byte.
The second form says treat 'm' as if it is a structure of the specified type and write directly to the memory cell at the specified offset from this location.
Exactly what the code does.

Best Wishes
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Feb 12, 2012 3:38 am     Reply with quote

Quote:
I don't think there's anything philosophical about this. It's wrong and you know it's wrong. The odds are it's a bug that CCS will fix in the next version, so there's no point trying to take advantage of it.

Yes. But literally it's not a bug, I think. It's a case of incomplete error diagnostics where the compiler accepts wrong C syntax and translates it somehow. Here the lower byte of the pointer is overwritten.

The requirements for error diagnostics are different in various C standards. ANSI C basically requires it. CCS C however has a more casual error diagnostic and does only rarely warn about dubious code constructs.

Compared e.g. to GCC working in the Microchip C30 or C32 compiler, it can be improved a lot.

P.S.:
Quote:
The second form says treat 'm' as if it is a structure of the specified type and write directly to the memory cell at the specified offset from this location.

Yes, "as if it is". But it isn't. The discussion is about the necessity to detect this.

GCC reports an error for m.value = 5;
Quote:
error: request for member 'value' in something not a structure or union

P.P.S.: To make the wrong assignment acceptable for a compiler with full syntax error diagnostics, you need to write
Code:
(*(my_struct_type*)&m).value = 5;
jeremiah



Joined: 20 Jul 2010
Posts: 1346

View user's profile Send private message

PostPosted: Sun Feb 12, 2012 7:40 am     Reply with quote

I actually didn't catch that one was using direct and the other indirect, thanks. I think the #0 before the 802 made my brain go into "they're different modes" mode, so I missed that. I should have caught it with the dot operator disassembly though, so I goofed there. Brain malfunction. That makes me feel better.

I tend to struggle with a lot of CCS related things and whether to use them (overloaded function names for example). Given that this doesn't do what I thought it was doing makes it an easier choice.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group