|
|
View previous topic :: View next topic |
Author |
Message |
ralph79
Joined: 29 Aug 2007 Posts: 87
|
Strange problem compiler versions |
Posted: Sat Apr 05, 2014 2:54 am |
|
|
Hi all,
I have a code that was built in ccs 4.085 for the PIC16F1824 that was sort of array of reference of variables:
Code: |
const signed char default_params[28] = {default_vary1, default_vary2, default_vary3, default_vary4, default_vary5};
signed char *def_params[5] = {&vary1, &vary2, &vary3, &vary4, &vary5};
volatile int8 temp = 0;
int8 i = 0;
for (i = 0; i < 5; i++)
{
temp = read_eeprom(i);
if (temp == 0xFF)
{
temp = default_params[i];
}
def_params[i] = temp;
}
if (0x25 === vary1)
{
// the normal function
}
|
With the version 4.085 this works perfectly well.. but with the 5.020 it doesn't work... it gives the reference/position of the variable "vary1" and not the value of "vary1". Why?
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Apr 05, 2014 8:33 am |
|
|
Because that is what you are declaring it as.
It looks like the older compiler was faulty here, and your program was taking advantage of the fault.
The declaration:
signed char *def_params[5] = {&vary1, &vary2, &vary3, &vary4, &vary5};
Is saying this is an array of five _pointers_ to values. Not the values....
You store the addresses of the variables. |
|
|
ralph79
Joined: 29 Aug 2007 Posts: 87
|
|
Posted: Sat Apr 05, 2014 9:49 am |
|
|
Hi Ttelmah,
The reason for this is the following:
First: the declaration of each variable:
Code: |
signed char vary1 = 0;
........
signed char vary5 = 0;
|
also, I need this array of variables because I receive the information of the value of each variable from a PC. So I have an array of values that fills each of the variable that I need. After refresh each variable I make also an array of eeprom saves to save the value of each variable.
Also, if there is no value saved in the eeprom, by the default I have a certain values.
So I need to use the variable value.. always... is there any other way to do this?
Regards |
|
|
ralph79
Joined: 29 Aug 2007 Posts: 87
|
|
Posted: Sat Apr 05, 2014 9:57 am |
|
|
Also,
I have a very similar code in a PIC32 micro with the XC32 V.120 and now V.30 and it works perfectly well. The code is the same.
So I think that it must be an problem of the compiler and I have to make an workaround. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Sat Apr 05, 2014 11:21 am |
|
|
The problem is that:
def_params[i]
is the address of the variable. You then write a value directly to this, which will then be used as the address. *def_params[i] is the value.
*def_params[i] = temp;
is the way to write to the variable itself.
Seriously, arrays of pointers, is a thing that CCS gets wrong in various ways in different version. I've suggested in the past using arrays of long integers instead, and explicitly casting the pointer to a long integer and back when needed.
So:
Code: |
long int def_params[5] = {&vary1, &vary2, &vary3, &vary4, &vary5};
volatile int8 temp = 0;
int8 i = 0;
for (i = 0; i < 5; i++)
{
temp = read_eeprom(i);
if (temp == 0xFF)
{
temp = default_params[i];
}
*((signed char *)def_params[i]) = temp;
}
if (0x25 === vary1)
{
// the normal function
}
|
Forces correct operation of the pointers.
Now understand that you are not using reference parameters, since you don't pass this to a function. If you passed with the & format to a function, this becomes a reference parameter, and talking directly to the variable would affect the original copy. This would work allow the value to be used as you show. |
|
|
ralph79
Joined: 29 Aug 2007 Posts: 87
|
|
Posted: Sun Apr 06, 2014 1:38 pm |
|
|
Dear Ttelmah,
I use this structure of arrays to save flash memory...because in fact I have 30 variables stored in this array.
I use the value of each variable by the name of each variable
Code: | if (0x25 == vary1)
{
}
else if (0x19 == vary2)
{
}
else if (temp_sensor4 == vary3)
{
} |
But for update, each variable, or for send the value of each variable to the PC (populate) the buffer I use array of pointers. Also, for example if I have more variables, I can easily increase the max_num_variables and the way of work is practical the same.
But yes, the most important part is to reduce the size of the flash memory
Also for receiving the data of the PC I use, for updating/changing the value of each variable:
Code: | for ( i = 0; i < max_num_variables; i++)
{
def_params[j] = rs_rcv_buffer[i+3];
} |
and for sending the information of the actual value of each value for the PC I use the following:
Code: | for (i = 0; i < max_num_variables; i++)
{
rs_send_buffer[rs_send_pointer++] = def_params[i];
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Mon Apr 07, 2014 12:30 am |
|
|
You are missing the point.
What you are trying to do, is _incorrect C_.
When you say 'similar' for XC32. I'm sure it is not _the same_.
Now understand that an array of pointers is legal C, but you then have to talk to the elements, by accessing the elements, not the pointer.
The exception is an item passed 'by reference' to a function, where '&' is used in the function declaration, and the compiler then sorts out handing the pointer to the function, and dereferences this, so the function can use it as if it was a local variable. Despite your thread title, this is not what you are doing.
That it worked in the old compiler, simply tells you that the old compiler was getting this wrong....
Now the various CCS compilers do commonly get this wrong, and don't handle arrays of pointers well between different versions. I've shown you how instead to store an array of integers, which you load with pointer values, and use as pointers (with a cast). To make this tidy, declare a macro to do this. This works with really old CCS compilers, and modern ones alike (which avoids problems as you update versions). |
|
|
ralph79
Joined: 29 Aug 2007 Posts: 87
|
|
Posted: Mon Apr 07, 2014 2:12 am |
|
|
Dear Ttelmah,
In the xc32 I do the following:
Code: | signed char vary1, vary2, vary3, vary4, vary5;
const signed char default_params[] = {default_vary1, default_vary2, default_vary3, default_vary4, default_vary5};
char *def_params[4] = {&vary1, &vary2, &vary3, &vary4, &vary5}; |
Accessing the variables:
Code: | for (i = 0; i < num_max_var; i++)
{
*def_params[i] = rs_rcv_buffer[i + 2];
} |
sending/update variables:
Code: | rs_send_buffer[rs_send_pointer++] = *def_params[Parameter_to_Change]; |
The idea is to have an array/structure with the value of each variable.
I can't double check if is totally incorrect C because in the past with the GNU compiler and the Visual Studio Compiler I have made similar things to this.
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Mon Apr 07, 2014 2:50 am |
|
|
Yes. Notice the critical extra '*'.....
Exactly what I pointed out in my second post:
Quote: |
*def_params[i] = temp;
is the way to write to the variable itself.
|
You are writing to the pointer, not the variable.....
Use the syntax you had with xc32. |
|
|
ralph79
Joined: 29 Aug 2007 Posts: 87
|
|
Posted: Mon Apr 07, 2014 3:08 am |
|
|
In the ancient ccs version if I put the "*" I have an error on compiling...
that was the reason I remove it.
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19504
|
|
Posted: Mon Apr 07, 2014 3:23 am |
|
|
Yes.
As I said:
"It looks like the older compiler was faulty here, and your program was taking advantage of the fault."
also:
"Now the various CCS compilers do commonly get this wrong, and don't handle arrays of pointers well between different versions." |
|
|
|
|
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
|