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

Assigning the base address of a 2 dim array to a pointer

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



Joined: 14 Jun 2006
Posts: 31

View user's profile Send private message

Assigning the base address of a 2 dim array to a pointer
PostPosted: Wed Jul 29, 2009 2:04 pm     Reply with quote

Hello,

I am using PCWH version 4.095 with PIC 18FL4685 and the programming language is C.

I would like to assign the base address of a two dimensional array to a pointer, and then use that pointer to access informations from the array using the double subscript notation format as:

subscript[0][0];

So basically here is the code:

Code:
#include <Dv4685.h>              // DEVICE INNITIALIZATIONS
#include <stdlib.h>              // CCS LIBRARY STANDARD LIBRARY
#include <stdlibm.h>             // CCS LIBRARY (HEAP) MALLOC MODULE

int main()
{
long *h, t;

long pmr[2][5] = { {195,  989,  193, 111, 111 },
                   {194,  195,  112, 222, 111 } };

h = pmr;  // Assign the array's base address to a pointer

// Instead of accessing the array's data like this:
//t = *h;
//t = *(h+1);
//t = *(h+2);

// I would like to access the array's data using this format using the pointer:
t = *(h)[0][0];
t = *(h)[0][1];
t = *(h)[0][2];

return 0;
}


I know that I can use pointer arithmetic, but I am very curious if it can be done using normal accesing method as shown in example above?

All feedback appreciated!

Robert
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 29, 2009 2:09 pm     Reply with quote

Quote:

I am very curious if it can be done using normal accesing method as
shown in example.

Test it, and tell us if it works or not.
Guest








PostPosted: Wed Jul 29, 2009 2:51 pm     Reply with quote

I did test it and I get the following error:

too many subscripts?

I don't know how else this would work?
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Jul 29, 2009 3:20 pm     Reply with quote

You can't dereference h to a two-dimensional array, because the size of the first dimension is unknown to the compiler. Also *h[0][0] is a wrong level of indirection.

You can access the array elements by mapping them to a one-dimensional array, or you would have to define a long[2][5] typed pointer explicitely.
Code:
h = pmr;  // Assign the array's base address to a pointer
t =  h[0*5 + 0]; //h[0][0];
t =  h[0*5 + 1]; //h[0][1];
t =  h[0*5 + 2]; //h[0][2];
t =  h[1*5 + 0]; //h[1][0];
rougie



Joined: 14 Jun 2006
Posts: 31

View user's profile Send private message

PostPosted: Wed Jul 29, 2009 5:18 pm     Reply with quote

Hi Fvm,

Quote:

You can access the array elements by mapping them to a one-dimensional array

h = pmr; // Assign the array's base address to a pointer
t = h[0*5 + 0]; //h[0][0];
t = h[0*5 + 1]; //h[0][1];
t = h[0*5 + 2]; //h[0][2];
t = h[1*5 + 0]; //h[1][0];

Okay, that I am aware of!

But then, does CCS PCWH compiler allow us to do the following:
Quote:
or you would have to define a long[2][5] typed pointer

and if so, how?

I am confused!
Regards Robert
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Jul 30, 2009 1:14 am     Reply with quote

I see that the common C syntax for typed pointers to an array isn't accepted by PCH, e.g.:
Code:
long (*h1)[5];
long (*h2)[2][5];

but multi-dimensional arrays can be constructed by hierarchical structs, as far as I remember. In the present case, the suggested index arithmetic is the most simple solution, I think.
rougie



Joined: 14 Jun 2006
Posts: 31

View user's profile Send private message

PostPosted: Thu Jul 30, 2009 9:58 am     Reply with quote

Hello FvM,
Quote:
I see that the common C syntax for typed pointers to an array isn't accepted by PCH, e.g.: "

Code:
long (*h1)[5];
long (*h2)[2][5];

I thought so! I was able to create an explicit type pointer of that sort:
Code:
long (*h1)[5]

In a .c file but compiled in VC++ environment (VC++ accepts C programs) and it did work fine but as you say I could not get this to work in PCWH.

Well I think I will stick to pointer arithmetic.

FvM, there is something else which I don't understand, if you may permit me to express my question!

Please view the following snippet of code:

Code:
#include <Dv4685.h>              // DEVICE INNITIALIZATIONS
#include <stdlib.h>              // CCS LIBRARY STANDARD LIBRARY
#include <stdlibm.h>             // CCS LIBRARY (HEAP) MALLOC MODULE

int main()
{
long *h, t;

long pmr[2][5] = { {195,  989,  193, 111, 111 },
                   {194,  197,  112, 222, 333 } };

h = pmr;

t = *((long*)h);
t = *((long*)(h+1));  // inc by 1
t = *((long*)(h+2));  // inc by 1

return 0;
}


In the above snippet, I am able to assign the two dimensional array's base address to a pointer called "h".

Then, I am able to use pointer arithmetic to access all the values in the two dimensional array *and* I do this by simply incrementing the pointer's address by 1 as shown above!

Now please take a look at this other snippet:

Code:

#include <Dv4685.h>              // DEVICE INNITIALIZATIONS
#include <stdlib.h>              // CCS LIBRARY STANDARD LIBRARY
#include <stdlibm.h>             // CCS LIBRARY (HEAP) MALLOC MODULE

typedef struct tag_lb
{
long pmr;
}lb;

int main()
{
long t;
lb  *pObj = NULL;

long pmr[2][5] = { {195,  700,  193, 111, 111 },
                   {194,  195,  112, 222, 111 } };

pObj = malloc (sizeof  *pObj);
pObj->pmr = pmr;   

t = *((long*)  pObj->pmr);
t = *((long*)((pObj->pmr)+2));  // inc by 2 ?
t = *((long*)((pObj->pmr)+4));  // inc by 2 ?
return 0;
}



In the example above the base address (pmr) is used indirtectly. Innitially, I assigned it to a long pointer member of the tag_lb structure called pmr. Then I simply fetch the pmr pointer whcih still contains the base address of the two dimensional array like this:

Code:
t = *((long*)  pObj->pmr);


As you can see, in the line above, I dereference the pointer get the contents of the two dimensional array. The problem is, that I have to do the base address +2 instead of +1 ?

I tried this piece of code in another C compiler and it works with +1. Why in PCWH, we have to do +2 ?

I really would like to know if this is specific to the PCWH compiler?

FvM, I thankyou for your help!

Finest regards
Robert!
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Jul 30, 2009 3:21 pm     Reply with quote

As a first comment, your pointer arithmetic variant is generating the same binary code as the one-dimensional array access I suggested previously. It can be simplified, because h is already a long pointer, thus these three lines are equivalent
Code:
t = *((long*)(h+1));  // inc by 1
t = *(h+1);  // inc by 1
t = h[1];


I don't exactly understand, why pObj is apparently treated as untypified pointer, so the respective pointer arithmetic uses a byte increment. But you can cast it to a long (int16) pointer.
Code:
t = *(((long*)pObj->pmr)+1);

This variant is generating a considerable code size overhead anyway and shouldn't be used, I think.
Guest








PostPosted: Thu Jul 30, 2009 4:24 pm     Reply with quote

Hello FvM,

Quote:

I don't exactly understand, why pObj is apparently treated as untypified pointer so the respective pointer arithmetic uses a byte increment.

Isn't pObj a pointer typified as an lb type?

Not supposed to! I have tried it in other compilers and works fine lke this:

Code:
t = *(((long*)pObj->pmr)+1);

as opposed to having to add 2 all the time.

Quote:
But you can cast it to a long (int16) pointer.

type casting pObj, would not make the pointer an *lb type anymore. No?

I don't know, this is driving me up a wall. I don't understand this and I really feel like I need to grasp the fundamental understanding of this issue.

FvM I appreciate your help... should you see something I am not seeing, please do get back, I would be greatful.

Finest regrads
Robert
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Fri Jul 31, 2009 12:51 am     Reply with quote

Quote:
Isn't pObj a pointer typified as an lb type?
Not supposed to! I have tried it in other compilers and works fine lke this:
I think, it's correct C syntax, but not correctly understood by CCS C.
Quote:
type casting pObj, would not make the pointer an *lb type anymore.
Not exactly, but it works anyway in this case.
rougie



Joined: 14 Jun 2006
Posts: 31

View user's profile Send private message

PostPosted: Fri Jul 31, 2009 7:50 am     Reply with quote

Hello FvM,

Well that sums that up!

Its been nice chatting with you, I wish you a nice day!

P.S. I thank you for your help!

Finest Regards
Robert
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