View previous topic :: View next topic |
Author |
Message |
hmmpic
Joined: 09 Mar 2010 Posts: 314 Location: Denmark
|
Pointer warning.... |
Posted: Tue May 10, 2016 4:46 am |
|
|
After compiler update 5058 I get a lot of Pointer warning, why??
It is a program there have worked for years, and still work but all the warning?
-All int are int8! (PIC18F26K22)
1)
Code: | Struct{
//A lot of data
}EEData;
#define EEPosData &EEData,sizeof(EEData),10+1
void EEProm_PUT(int *ptr,int size,int addr) {
//...
}
void test1(){
EEProm_Put(EEPosData); //-> pointer warning
}
|
2)
Code: | int8 AssignFastSetup(char **ptr){
//...
}
void test2(){
char *Cmdptr[12]; //pointer to string.
AssignFastSetup(Cmdptr); //-> Pointer warning
}
|
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue May 10, 2016 5:15 am |
|
|
1) &EEData is not an int* it is an (struct EEData *) type. You have to cast it to int * if you want the warning (which is a correct warning) to go away.
Code: |
#define EEPosData (int *)&EEData,sizeof(EEData),10+1
|
should fix it
2) Not sure why this one complains as I would expect char *Cmdptr[12] to be of type char **. I would send CCS support an email and ask.
Side note:
I would be weary of using
Code: | char *Cmdptr[12]; //pointer to string. |
This declaration doesn't allocate any memory or guarantee any actual size. If the function is returning a static variable address, then you should be using char ** Cmdptr instead. If you think it is allocating a 12 character array, it isn't. Either way, the declaration would be misleading. |
|
|
hmmpic
Joined: 09 Mar 2010 Posts: 314 Location: Denmark
|
|
Posted: Tue May 10, 2016 5:56 am |
|
|
Thanks.
1)
I will change that. Thanks.
2)
char *Cmdptr[12];
It is 12 char pointers, to a already existing 200 byte char buffer. The buffer hold some communication data and the Cmdptr[x] only point into the pre defined buffer.... |
|
|
hmmpic
Joined: 09 Mar 2010 Posts: 314 Location: Denmark
|
|
Posted: Tue May 10, 2016 6:47 am |
|
|
Hmmm when casting (int8 *) warnings is gone, but the code is changed a lot in the .lst and take much more space. I cant understand all the change the compiler made but the code is complete changed?
I think I keep the warnings and the old wrong way. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Tue May 10, 2016 7:40 am |
|
|
This has been discussed here.
One simple answer, is just to turn that warning off....
However it is warning you because of the potential danger. Understand that a pointer, is just an address in memory. However pointers when declared and used, also have an implicit 'size'. So if you increment a int8 *, then it should increment by one, to point to the next int8. However if you increment a int32 *, then it should increment by 4 (the size of the int32) to point to the next int32.
Now you may well want to do this (when for instance, you hand a pointer into a function that internally treats it as int8 *, though the pointer is to a different type), but it was raised here by a poster that while 'C' historically allowed this without warning, later variants like ANSI C, do give a warning when the types do not agree. Hence CCS added the warning to 'point out' to you to beware that the sizes do not agree inside the function and outside.
Casting should not make the code any larger, provided you are actually doing it right. The odds are that the cast you are doing is effectively 'the wrong way', so you are making the function actually treat the pointer as being to the larger type, so more maths is involved..... |
|
|
hmmpic
Joined: 09 Mar 2010 Posts: 314 Location: Denmark
|
|
Posted: Tue May 10, 2016 8:00 am |
|
|
Some confusing.
Code: | Struct{
//A lot of data
}EEData;
#define EEPosData &EEData,sizeof(EEData),10+1
void EEProm_PUT(int *ptr,int size,int addr) {
//...
}
void test1(){
EEProm_Put(EEPosData); //-> pointer warning
} |
All the int are int8 size. Therefore why when casting the
#define EEPosData &EEData,sizeof(EEData),10+1
to
#define EEPosData (int8*)&EEData,sizeof(EEData),10+1
will that increase the code?
What I was doing is to get the address and the size of the EEData struct (I think you or "PCM Programmer" post the originally code some years ago, and I grap it and use it) and pass it to a handler function to save it in EEProm. It loop the sizeof(EEData) in byte... |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue May 10, 2016 10:29 am |
|
|
I would agree with Ttelmah. If the code changes to larger in size simply from casting, the odds are something is being done wrong (statistically a more likely scenario) or there is a compiler bug (lower chance, but still likely). Either way, you should verify because both scenarios can bite you later if you don't know what is causing it.
hmmpic wrote: | Thanks.
2)
char *Cmdptr[12];
It is 12 char pointers, to a already existing 200 byte char buffer. The buffer hold some communication data and the Cmdptr[x] only point into the pre defined buffer.... |
Gotcha. I worded that poorly anyways. I was worried you were thinking those 12 pointers already had memory allocated for them. Didn't realize you had a buffer (hopefully static or global) that they pointed to. Always hard to troubleshoot blind. |
|
|
hmmpic
Joined: 09 Mar 2010 Posts: 314 Location: Denmark
|
|
Posted: Tue May 10, 2016 10:49 am |
|
|
Please try this small working demo, it is not for production only for demo.
Then take a look at the lst file. It generate bigger code and some confusing.
Code: | #include <18f26k22.h>
//Only demo prog, not for a PIC.
struct{
int16 x;
int8 y;
char c;
char s[20];
}EEData;
#define EEPosData1 &EEData,sizeof(EEData),10+1 //warning
#define EEPosData2 (int8 *) &EEData,sizeof(EEData),10+1 //NO Warning
void EEProm_Put(int8 *ptr,int8 size,int8 addr) {
int8 count;
for (count=0;count<size;count++) { WRITE_EEPROM(addr+count,ptr[count]); }
}
void main(void){
//EEData=0;
EEProm_Put(EEPosData1);
//one more call
EEProm_Put(EEPosData2);
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 10, 2016 11:31 am |
|
|
The best way to do it in my opinion, is to use typedef. Create a new
type involving your structure, and name the type some unique useful
name, such as xycs_t. Then create an instance of this type and name
the instance EEData. I always do it this way.
Then in your function declaration for EEProm_Put(), declare the first
parameter to be of type 'xycs_t'. Once you do it like this, you get no
errors, the compiler is happy and the program is better. The program is
accurate.
Code: |
#include <18F26k22.h>
#fuses INTRC_IO, NOWDT
#use delay(clock=4M)
typedef struct{
int16 x;
int8 y;
char c;
char s[20];
}xycs_t;
xycs_t EEData; // Create one instance of the xycs_t data type
//--------------------------
void EEProm_Put(xycs_t *ptr, int8 size, int8 addr)
{
int8 count;
for(count=0;count<size;count++)
{
write_eeprom(addr+count,ptr[count]);
}
}
//========================
void main(void)
{
EEProm_Put(&EEData, sizeof(EEData), 10+1);
while(TRUE);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Tue May 10, 2016 11:40 am |
|
|
One instruction different. It just copies the value into a separate variable.
However as I said, just add:
#IGNORE_WARNINGS 240
up near the top of your code, and it'll behave exactly as it used to.
The best way really is to make the pointer types match - see PCM_Programmer has already shown 'how'. |
|
|
hmmpic
Joined: 09 Mar 2010 Posts: 314 Location: Denmark
|
|
Posted: Tue May 10, 2016 11:51 am |
|
|
Hi
"PCM Programmer", will you please take a look at the lst file, and see the function "EEProm_Put", this is real confusion. Now it consume 4 times than before? What is going on I cant find out. I think i just disable the warning for this working program. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 10, 2016 12:11 pm |
|
|
I'm not seeing it in the .LST file. Can you post two programs ?
One program that produces small code, and a 2nd program that
produces large code. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19520
|
|
Posted: Tue May 10, 2016 1:16 pm |
|
|
For me, the size doesn't change. |
|
|
hmmpic
Joined: 09 Mar 2010 Posts: 314 Location: Denmark
|
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1349
|
|
Posted: Tue May 10, 2016 2:40 pm |
|
|
Disclosure: I have 5.056 (still waiting on IT to install 5.058)
Note that PCM's example has Fuses and #use delay where hmmpic's example does not. That adds some small amount code I think. Even so:
For me it depends on if I use copy/paste from PCM's example or if I further cast the pointer going into write_eeprom call
With
Code: |
write_eeprom(addr+count,ptr[count]);
|
I get:
Code: |
File Summary:
Filename: D:\__workspaces\CCS\pic24fjtest\main.hex
File Status: Good
Target Chip: PIC18F26K22
File Type: INHX32 (Intel Hex)
Program Size: 181 Instructions (1%)
Program Range: 0000-0169
Data EE Size: 0 bytes
Checksum: 6050
Config Size: 14 bytes
Created: 10-May-16 16:36
Addresses are: Byte addresses
Program Memory
000000: EFA1 F000 5022 0224 CFF3 F001 CFF4 F000
000010: 0225 50F3 2600 5023 0224 50F3 2000 6E02
000020: EF21 F000 6A20 501E 5C20 B0D8 D088 5020
000030: 241F 6E21 6A23 C020 F022 6A25 0E18 6E24
000040: D7E1 C002 F003 5001 241C 6EE9 501D 2003
000050: 6EEA 52EE 52EE 52EE 52EE 52EE 52EE 52EE
000060: 52EE 52EE 52EE 52EE 52EE 52EE 52EE 52EE
000070: 52EE 52EE 52EE 52EE 52EE 52EE 52EE CFEC
000080: F039 52ED CFEF F038 52ED CFEF F037 52ED
000090: CFEF F036 52ED CFEF F035 52ED CFEF F034
0000A0: 52ED CFEF F033 52ED CFEF F032 52ED CFEF
0000B0: F031 52ED CFEF F030 52ED CFEF F02F 52ED
0000C0: CFEF F02E 52ED CFEF F02D 52ED CFEF F02C
0000D0: 52ED CFEF F02B 52ED CFEF F02A 52ED CFEF
0000E0: F029 52ED CFEF F028 52ED CFEF F027 52ED
0000F0: CFEF F026 52ED CFEF F025 52ED CFEF F024
000100: 52ED CFEF F023 52ED CFEF F022 50F2 6E00
000110: 9EF2 6AAA C021 FFA9 C022 FFA8 9CA6 9EA6
000120: 84A6 010F 0E55 6EA7 0EAA 6EA7 82A6 B2A6
000130: D7FE 94A6 5000 12F2 2A20 0100 D774 EFB3
000140: F000 6AF8 9ED0 010F 6B38 6B39 6B3A 6A77
000150: 6A78 6A79 6A1D 0E04 6E1C 0E18 6E1E 0E0B
000160: 6E1F 0100 D75F D7FF 0003
Configuration Words
300000: FF00 3C1E BF00 0081 C00F E00F 400F
;PIC18F26K22
;CRC=C5EF CREATED="10-May-16 16:36"
|
but with
Code: |
write_eeprom(addr+count,((int8*)ptr)[count]);
|
I get
Code: |
File Summary:
Filename: D:\__workspaces\CCS\pic24fjtest\main.hex
File Status: Good
Target Chip: PIC18F26K22
File Type: INHX32 (Intel Hex)
Program Size: 64 Instructions (1%)
Program Range: 0000-007F
Data EE Size: 0 bytes
Checksum: BA2F
Config Size: 14 bytes
Created: 10-May-16 16:37
Addresses are: Byte addresses
Program Memory
000000: EF2C F000 6A20 501E 5C20 E224 5020 241F
000010: 6E21 5020 241C 6EE9 0E00 201D 6EEA CFEF
000020: F022 50F2 6E00 9EF2 6AAA C021 FFA9 C022
000030: FFA8 9CA6 9EA6 84A6 010F 0E55 6EA7 0EAA
000040: 6EA7 82A6 B2A6 D7FE 94A6 5000 12F2 2A20
000050: 0100 D7D9 EF3E F000 6AF8 9ED0 010F 6B38
000060: 6B39 6B3A 6A77 6A78 6A79 6A1D 0E04 6E1C
000070: 0E18 6E1E 0E0B 6E1F 0100 D7C4 D7FF 0003
Configuration Words
300000: FF00 3C1E BF00 0081 C00F E00F 400F
;PIC18F26K22
;CRC=83BD CREATED="10-May-16 16:37"
|
This is actually smaller than hmmpic's code as well. The example PCM posted appears to dereference the pointer of type xycs_t, which would be a full struct, not a byte (am I reading this wrong??). I don't know how write_eeprom accepts a value of that type.
EDIT: this is the fully modified PCM example that gave the smallest hex file. I took out the #fuses and clock statement to make it similar to hmmpic's and cast the value in the write_eeprom call
Code: |
#include <18F26k22.h>
typedef struct{
int16 x;
int8 y;
char c;
char s[20];
}xycs_t;
xycs_t EEData; // Create one instance of the xycs_t data type
//--------------------------
void EEProm_Put(xycs_t *ptr, int8 size, int8 addr)
{
int8 count;
for(count=0;count<size;count++)
{
write_eeprom(addr+count,((int8*)ptr)[count]);
}
}
//========================
void main(void)
{
EEProm_Put(&EEData, sizeof(EEData), 10+1);
while(TRUE);
}
|
|
|
|
|