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

passing array of structures

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



Joined: 02 Feb 2010
Posts: 354

View user's profile Send private message

passing array of structures
PostPosted: Wed Apr 18, 2018 5:37 am     Reply with quote

Hello Everyone,

What is the true way to passing array of struct to function? Below example does not work correct!


Code:

char str1[] = "123456";

typedef struct {
   
   int8 arr1[6];
   int8 arr2[12];
   
}st;

st st1;

#zero_ram
void main(){
   
   delay_ms(500);
   
   memcpy(st1.arr1, str1, 6);
   
   memcpy(st1.arr2, st1.arr1, 6);
   
   delay_ms(100);

   while(TRUE);
}


Best Regards!
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Wed Apr 18, 2018 7:01 am     Reply with quote

First problem is that str1, is seven characters long. There is not sufficient space in the arr1 to hold the string. Remember a 'string' in C, is an array of characters, with a terminating null added. str1 is seven characters long. You are copying it without it's terminating null....
The address will be correctly passed by what you show. You can use the 'explicit' form (&st1.arr1[0]), but either is syntactically correct, and the compiler will correctly accept either.
If you use strcpy, not memcpy. This will automatically copy the correct number of characters, but won' handle the destination not being large enough.....
kmp84



Joined: 02 Feb 2010
Posts: 354

View user's profile Send private message

PostPosted: Wed Apr 18, 2018 7:24 am     Reply with quote

Hi, Ttelmah,

I know about null terminating. It is only example to show you what is the problem. The real data is binary not string. Only first byte from str1 is copied to st1.arr1 and first byte from st1.arr1 to st1.arr2.

CCS C v.5.075, dsPic33EP512MU810.
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Wed Apr 18, 2018 7:46 am     Reply with quote

It merrily copies all six bytes for me on your chip & compiler version. Either your 'example' is not showing the real problem, or something else not included is making it go wrong.
kmp84



Joined: 02 Feb 2010
Posts: 354

View user's profile Send private message

PostPosted: Thu Apr 19, 2018 1:09 am     Reply with quote

Hi Ttelmah,

Everything works correctly! I thought this was not working because ICD U80 stopping on first byte after command "step over". Sorry for my mistake! Confused

I have another question about passing nested structure to function. Here is some test program.
Code:

#include <33EP512MU810.h>
#device ICSP=1
#use delay(crystal=8MHz, clock=32MHz)

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOJTAG                   //JTAG disabled
#FUSES NOPROTECT


/**************Test 3 ******************/

struct _st{
   
   int8 a;
   int8 b;
   
   rtc_time_t t1;  // <33EP512MU810.h>
   
   rtc_time_t t2;  // <33EP512MU810.h>
};

struct _st st[4];

void func(rtc_time_t &date_time){
   unsigned int8 a;
   
   a = date_time.tm_year;
}



#zero_ram
void main(){
   
   int8 i = 0;
   
   delay_ms(500);
   
   func(st[i].t1);
   
   delay_ms(100);

   while(TRUE);
}


The CCS compiler says: *** Error 105 "main.c" Line 100(15,17): Different levels of indirection
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Thu Apr 19, 2018 1:34 am     Reply with quote

It's right....

Think about it. Your 'func' is expecting to receive a pointer to an rtc_time_t type. You are passing it the variable.

func(&st[1].t1);

As structure name is _not_ automatically treated as an address. This is reserved for arrays. A structure name itself (so the outer container here), is always treated as a pointer, but this is reserved for the first element in a structure. So a structure inside a structure can't be used as a shortcut to it's address
kmp84



Joined: 02 Feb 2010
Posts: 354

View user's profile Send private message

PostPosted: Thu Apr 19, 2018 1:59 am     Reply with quote

Hi,

I have no idea how to workaround. Sad
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Thu Apr 19, 2018 2:48 am     Reply with quote

Er. I posted what you have to use.....
kmp84



Joined: 02 Feb 2010
Posts: 354

View user's profile Send private message

PostPosted: Thu Apr 19, 2018 3:49 am     Reply with quote

Hi Ttelmah,

You mean "func(&st[1].t1); ", which doesn't work! Also the struct array index is not const value!

Thanks.
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Thu Apr 19, 2018 4:12 am     Reply with quote

The reason it doesn't work, is your syntax in the function is wrong:
Code:

   a = date_time->tm_year;
//You are passing an _[u]address[/u]_ you need to work from this

func(&st[1].t1);

Will happily accept a variable index.
kmp84



Joined: 02 Feb 2010
Posts: 354

View user's profile Send private message

PostPosted: Thu Apr 19, 2018 5:10 am     Reply with quote

Finally it's working! Smile
Code:

#include <33EP512MU810.h>
#device ICSP=1
#use delay(crystal=8MHz, clock=32MHz)

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOJTAG                   //JTAG disabled
#FUSES NOPROTECT



#pin_select U3RX=PIN_G12   // Rx Com3.
#pin_select U3TX=PIN_G13   // Tx Com3.   

#use rs232(UART3,baud=115200,errors)   

/**************Test 3 [ok] ******************/

struct _st{
   
   int8 a;
   int8 b;
   
   rtc_time_t t1;
   
   rtc_time_t t2;
};

struct _st st[4];

void func(rtc_time_t *date_time){
   
   unsigned int8 a;
   unsigned int8 b;
   
   a = date_time->tm_year;
   b = date_time->tm_mon;
   
   printf("\r\n a: %u, b: %u", a, b);
}



#zero_ram
void main(){
   
   int8 i;
   
   delay_ms(500);
   
   i = 0;
   
   st[i].t1.tm_year = 18;
   st[i].t1.tm_mon = 4;
   
   func(&st[i].t1);
   
   delay_ms(100);

   while(TRUE);
}


I have to educate more myself with C language.
Shocked

Thanks Mr.Ttelmah!
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Thu Apr 19, 2018 6:28 am     Reply with quote

Yes.
One 'trick' that is well worth learning, is to use useful names. So in the rtc_time, they use rtc_time_t to say 'this is a type'. If you call pointers when they are passed fo functions, something like *date_time_ptr, then it gives you a really solid reminder in the function, that this is not the variable directly, but a pointer to it. Similarly there is a 'semi standard' in C to reserve things declared in ALL_UPPER_CASE as enums or defines. Then use explicit sizes (int8, int16 etc.), rather than assuming an 'int' is a particular size. Combine these, and it helps massively to keep track of what you are doing. Smile
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