pointers to an array

Go To Last Post
7 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi all,
Whilst I can succesfully write to elements of an array using pointers, I cannot read them back.

 *ch_ptr='x';    //works
 ch=*ch_ptr;     //does not work (ch is always 0)

I initially the variables, array & pointer as follows

char ch, ch_array[10], *ch_ptr=&ch_array[0];
//alternatively
char ch, ch_array[10], *ch_ptr=ch_array;

In both cases the pointer initializes to the starting address of the array OK.

Any ideas anyone??

Lee

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
int main(void) {
 char ch, ch_array[10], *ch_ptr=&ch_array[0];

 *ch_ptr='x';      //works 
 ch=*ch_ptr;
 PORTB = ch;
}

Certainly results in 0x78 in PORTB in my copy of the simulator as expected. However it is actually achieved using:

10:       int main(void) {
+00000049:   E788        LDI       R24,0x78       Load immediate
+0000004A:   BB88        OUT       0x18,R24       Out to I/O location

'c', 'ch_array', 'ch_ptr' never actually exist as the optimiser has discarded all them as it can see that their existence was pointless. That code can only have one result and that is 'x' going to the PORTB (volatile) address and so that's exactly what the compiler generated.

So I'm just wondering if you are misunderstanding the optimiser perhaps? (or maybe the hopeless "watch" window in a simulator or something? - clearly there is nothing "watchable" in any of this apart from the PORTB location in I/O memory)

Of course if I'd made the variables global I'd have seen something different:

char ch, ch_array[10], *ch_ptr=&ch_array[0];

int main(void) {
 *ch_ptr='x';      //works 
 ch=*ch_ptr;
 PORTB = ch;
}

Leads to the code:

char ch, ch_array[10], *ch_ptr=&ch_array[0];

int main(void) {
 *ch_ptr='x';      //works 
  92:	e0 91 60 00 	lds	r30, 0x0060
  96:	f0 91 61 00 	lds	r31, 0x0061
  9a:	88 e7       	ldi	r24, 0x78	; 120
  9c:	80 83       	st	Z, r24
 ch=*ch_ptr;
  9e:	e0 91 60 00 	lds	r30, 0x0060
  a2:	f0 91 61 00 	lds	r31, 0x0061
  a6:	80 81       	ld	r24, Z
  a8:	80 93 6c 00 	sts	0x006C, r24
 PORTB = ch;
  ac:	88 bb       	out	0x18, r24	; 24
}

which is maybe closer to what you may have been expecting?

(this is because they are not automatics with limited scope the compiler cannot "know" whether some other compilation unit may be going to access them so it has to generate code to access them)

On the whole these kind of "do nothing" test programs will just be gobbled up by the optimiser and it's not really valid to do this kind of thing. In fact, if I hadn't introduced PORTB as a volatile destination there would have been NO code generated by the first program at all.

Last Edited: Wed. Apr 8, 2009 - 12:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That code should absolutely work as it stands.
Maybe the results is affected by the code not shown?

/johan

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

That code should absolutely work as it stands.

But my point is that if the 'ch' result is not subsequently used in a volatile destination that code does nothing whatsoever and the compiler will recognise this and discard it. I guess this is 'work'ing in that the optimiser will recognise there is NO work here so won't do anything - which is correct.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

All of your examples are correct.

I am assuming that the first example uses variables that are declared in the second example.

Please post a compilable code. I can only guess that your first variables are declared differently.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Clawson & others.
My variables are declared as globals but I
will do some more testing & perhaps compile
with no optimization.

char morse_buffer32],*morse_pointer=morse_buffer,morse_ch;

I populate the array with a ascii string & then
before converting to morse code I need to read the characters out of the array etc.

	//following statement does NOT work
	morse_ch=*morse_pointer++;		
        morse_ch&=0x7f;

Will post back my findings.
Regards,
Lee

Edit.
Mmm looks like a buggy simulator. If I run the code about three or four lines past the code where ch should change, all of a sudden a whole lot of SRAM locations go RED and ch updates to the right value.

I learnt a fair deal with your comments regarding the optimizer.
Lee

Charles Darwin, Lord Kelvin & Murphy are always lurking about!
Lee -.-
Riddle me this...How did the serpent move around before the fall?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Mmm looks like a buggy simulator. If I run the code about three or four lines past the code where ch should change, all of a sudden a whole lot of SRAM locations go RED and ch updates to the right value.

No, this does not necessarily mean that the simulator is buggy. This is most likely the effect of the compiler being allowed to shuffle the generated machine code around as it sees fit to get it as effective as it can while still preserving the "semantic intention" of the C source code. This shuffling around means that there is no longer a clear mapping between (blocks of) machine instructions and source code statements.

Imagine that you have some source code (and I "pseudo-code" here):

statement1;
statement2;
statement3;

if you have optimization switched of you might get machine code that could look something like this in (commented) pseudo-assembler:

     ; Machine code generated from statement1
     anInstr Rx, Ry
     anotherInstr Rz, addr
     aThirdInstr Rz, Rx

     ; Machine code generated from statement2
     anInstr Rx, Ry
     anInstr Rp, Rq
     aThirdInstr Rr, Rp
     anotherInstr Rx, addr

     ; Machine code generated from statement2
     anotherInstr Rp, addr
     aThirdInstr Rn, Rm
     anInstr Rm, Rm

In this code you can execute the code stepwize in a simulator and it can map exactly between machine instructions and source lines.

Now turn on the optinizer, and the compiler decides that this will be sematically equivalent but more effective:

     anInstr Rx, Ry         ; Common for code from expression1 and expression2
     anotherInstr Rz, addr  ; Part of machine code generated from statement1
     aThirdInstr Rz, Rx     ; Part of machine code generated from statement1
     anotherInstr Rx, addr  ; Part of machine code generated from statement2
     anotherInstr Rp, addr  ; Part of machine code generated from statement3
     aThirdInstr Rn, Rm     ; Part of machine code generated from statement3
     anInstr Rm, Rm         ; Part of machine code generated from statement3
     anInstr Rp, Rq         ; Part of machine code generated from statement2
     aThirdInstr Rr, Rp     ; Part of machine code generated from statement2 

I just made that gibberish up, but I hope that you can spot the shuffle and elimination of duplicate instructions. This is the stuff that the optimizer might do.

Now, when simulating you must execute these assembler instructions in the order that they stand above. That is the nature of sequential execution of machine instructions.

When you start this sequence, where should that little arrow in the source window point? At statement1? Or at statement2?
When you have stepped over statement1 should the fact that we actually have executed parts of statement2 be reflected in the watch window or not?
Etc etc...

Now, do you see how the optimizer messes the machine code up to a state where, in general, we can not step through source code and see the effects we are expecting. The program will do what you wrote in the source code, but you can no longer follow that flow in the source code.

Cliffs advice often is, switch to the disassembly view and watch the disassembled machine code as you execute. This will mean that you will need to learn some AVR Assembler, but if you have the need to see what is really happening (rather than accept that some things won't happen exactly when you step over an instruction in the source) then there is no way around it. You need to know AVR Assembler and figure out what the compiler did by reading the (obfuscated) machine code.

HTH!

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]