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

More pointer confusion [SOLVED]

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



Joined: 29 Jan 2015
Posts: 47
Location: United Kingdom

View user's profile Send private message

More pointer confusion [SOLVED]
PostPosted: Mon Oct 10, 2016 6:13 am     Reply with quote

Hi guys,

I thought I had a reasonable understanding of pointers until the following problem popped up:-

Code:

void func1( void )
{
    int8 * srcDataPtr;
   
    // Set up pointer to access channel data within struct
    srcDataPtr = &Uart2ParseBuf.data;
   
    if ( flags.channels & 0b00000011 ) {
        func2( &SpiPicABuf, srcDataPtr );
    }
   
    if ( flags.channels & 0b00001100 ) {
        func2( &SpiPicBBuf, srcDataPtr );
    }   
}


void func2( SpiBufT * buf, int8 * dataPtr )
{   
    bufSpiData( &buf->tx, *dataPtr );
    // Increment the pointer - I want this to increment the original
    // address pointed to by srcDataPtr in func1 too... How?
    dataPtr++;
}


I know that when I'm passing srcDataPtr to func2 it will make a copy of it at a different address. But when I increment the pointer in func2 how do I get it to change the address of the original pointer created in func1, i.e. srcDataPtr?

I've tried using **ptr as the argument to func2 but this doesn't seem to work.

Please help,

Thanks in advance,

Keith


Last edited by kWoody_uk on Tue Oct 11, 2016 2:55 am; edited 2 times in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Mon Oct 10, 2016 8:08 am     Reply with quote

Think about it:

Uart2ParseBuf.data - variable in memory

srcDataPtr - address of this variable

You can copy this latter as many times as you want, it still points to the same address.

Now you don't actually show func2 being called at all, but if it was being called where bufChDataForSpi is shown, then:
Code:
(*dataPtr)++;

inside the routine, would increment the value being pointed to by DataPtr.

This is all down to operator precedence.
Code:

    dataPtr++;

increments the local copy of the pointer. Effectively does nothing, since this is lost when the routine exits....
kWoody_uk



Joined: 29 Jan 2015
Posts: 47
Location: United Kingdom

View user's profile Send private message

PostPosted: Mon Oct 10, 2016 9:27 am     Reply with quote

Hi Ttelmah,

Sorry, I didn't make myself clear: I have edited my first post to correct my simplification of function names. And you are correct: I did intend to call func2.

I do understand what you're saying about the dataPtr increment being useless inside func2, but how would I change the address pointed to by the srcDataPtr (in func1) from inside of func2 - when I'm just working on a copy of the pointer?

Sorry if this is unclear.

Keith
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Mon Oct 10, 2016 11:45 am     Reply with quote

Why would you want to change the address?.
You can increment the contents as I show.
If you want to change the address, then just have the function return the new value.
jeremiah



Joined: 20 Jul 2010
Posts: 1353

View user's profile Send private message

PostPosted: Mon Oct 10, 2016 11:59 am     Reply with quote

pointer to a pointer: **var_name

Code:

void func2( SpiBufT * buf, int8 ** dataPtr )
{   
    bufSpiData( &buf->tx, **dataPtr );
    // Increment the pointer - I want this to increment the original
    // address pointed to by srcDataPtr in func1 too... How?
    (*dataPtr)++;
}



Code:

if ( flags.channels & 0b00001100 ) {
     func2( &SpiPicBBuf, &srcDataPtr );
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Tue Oct 11, 2016 1:22 am     Reply with quote

He is not actually doing that though.

It appears that he simply has an 'address' of some sort held in a structure.

He then takes a pointer to that address and passes this to a routine. He then seems to just want to increment the original address. The routine has a copy of the original pointer. No need for double references at all. If he increments the contents of the pointer, he is incrementing the original address.

However, general comment. every level of indirection you use (pointers to pointers etc.), costs _time_. Look at how ex_sisr.c, handles it's serial buffered data. Simply has counts, which can be incremented, and used as indexes to an array. Even this costs some time, but it's a lot simpler and has less overhead than multiple levels. Also makes limit checking easy, since otherwise if you increment the contents of a pointer to a pointer, how is the code going to know what limits it should apply to this?. Sure fire way of ending up with data disasters.... Think carefully about whether a simpler approach would be better.

To do what he is describing (increment the address at the 'middle' layer), as Jeremiah shows, you have to pass the address of this variable to the next routine (or you could use pass by reference). However this makes you potentially have the danger of the three addresses getting incorrectly aligned to each other, talking to different locations, and makes limit checking even harder... Crying or Very sad
kWoody_uk



Joined: 29 Jan 2015
Posts: 47
Location: United Kingdom

View user's profile Send private message

PostPosted: Tue Oct 11, 2016 2:51 am     Reply with quote

Thanks jeremiah,

That's exactly what I wanted to do. I did try to use pointer to pointer syntax, but I didn't get it quite right. I was using MPLAB sim to help me understand the C but it was flummoxing me!

Ttelmah:-
Quote:

He then takes a pointer to that address and passes this to a routine. He then seems to just want to increment the original address. The routine has a copy of the original pointer. No need for double references at all. If he increments the contents of the pointer, he is incrementing the original address.

I did want to increment the original address pointed to by srcDataPtr inside func2, but I then wanted it to remain incremented after func2 exited, and not revert to the original address pointed to by srcDataPtr.

I was getting stuck by the fact that when the pointer was passed to func2, a copy of the pointer was being made inside the function. I then incremented the address pointed to by the pointer, but after the function exited, this increment is lost, so the next time I used the func2 call the address pointed to was back to the original (pointed to by srcDataPtr).

A diagram would have been easier to explain, but I didn't know how to add images on here.

Point taken on extra time though Ttelmah. How would you do "pass by reference"? Is this the thing mentioned in CCS manual?

Thanks all for your help as usual.

Keith
Ttelmah



Joined: 11 Mar 2010
Posts: 19537

View user's profile Send private message

PostPosted: Tue Oct 11, 2016 3:01 am     Reply with quote

'Pass by reference', is technically a C++ ability. However CCS supports a slightly 'limited' form of it, though it will do exactly what you appear to want:

Code:

void func1( void )
{
    int8 * srcDataPtr;
   
    // Set up pointer to access channel data within struct
    srcDataPtr = &Uart2ParseBuf.data;
   
    if ( flags.channels & 0b00000011 ) {
    //No & or * here
        func2( &SpiPicABuf, srcDataPtr );
    }
   
    if ( flags.channels & 0b00001100 ) {
        func2( &SpiPicBBuf, srcDataPtr );
    }   
}


void func2( SpiBufT * buf, int8 &dataPtr )
//note the '&' here
{   
    //dataPtr is now a reference _[u]to[/u]_ srcDataPtr. If you increment
    //it here srcDataPtr will actually get incremented
    bufSpiData( &buf->tx, *dataPtr );
    //This will actually increment srcDataPtr
    dataPtr++;
}


Look at 'Reference Parameters' in the manual.
kWoody_uk



Joined: 29 Jan 2015
Posts: 47
Location: United Kingdom

View user's profile Send private message

PostPosted: Tue Oct 11, 2016 3:11 am     Reply with quote

Thanks Ttelmah - much appreciated.

Keith
jeremiah



Joined: 20 Jul 2010
Posts: 1353

View user's profile Send private message

PostPosted: Tue Oct 11, 2016 6:09 am     Reply with quote

One thing to watch out for when passing by reference: I don't know how other compilers do it, but in PCD, it tends to inline the function automatically when I have a reference parameter. Depending on the function, this can blow up the size of your code.

The other option you have is the one Ttelmah mentioned earlier about returning the new pointer value:

Code:

int8 * func2( SpiBufT * buf, int8 * dataPtr )
{   
    bufSpiData( &buf->tx, *dataPtr );
    // Increment the pointer - I want this to increment the original
    // address pointed to by srcDataPtr in func1 too... How?
    dataPtr++;
    return dataPtr;
}


Code:

if ( flags.channels & 0b00001100 ) {
     srcDataPtr = func2( &SpiPicBBuf, srcDataPtr );
}
kWoody_uk



Joined: 29 Jan 2015
Posts: 47
Location: United Kingdom

View user's profile Send private message

PostPosted: Tue Oct 11, 2016 8:58 am     Reply with quote

Thanks for the tips jeremiah. I'll watch out for those things.

I must admit, I've never used reference parameters - I'm not much of a C++ guy so just haven't found a use for them yet.

It certainly looks as if returning the new pointer value would be more transparent and more efficient code-wise.

Keith
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