|
|
View previous topic :: View next topic |
Author |
Message |
jeremiah
Joined: 20 Jul 2010 Posts: 1346
|
struct pointers and the dot operator |
Posted: Sat Feb 11, 2012 5:28 pm |
|
|
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
|
|
Posted: Sun Feb 12, 2012 1:17 am |
|
|
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
|
|
Posted: Sun Feb 12, 2012 3:05 am |
|
|
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
|
|
Posted: Sun Feb 12, 2012 3:38 am |
|
|
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
|
|
Posted: Sun Feb 12, 2012 7:40 am |
|
|
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. |
|
|
|
|
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
|