View previous topic :: View next topic |
Author |
Message |
ulg
Joined: 09 May 2019 Posts: 24
|
PIC18F252, CCS-IDE 3.249, passing an array |
Posted: Mon May 13, 2019 4:41 am |
|
|
I prefer to use 1st notation for passing an array, if I know the array's size, but this doesn't work in my actual program - I've to use the 2nd notation to get a working program, which overwrites tx[1] .. tx[3] when calling function ddOverWr(..).
I don't know, why?
1st notation:
Code: |
.................... void ddOverWr(tDd* p, char dat[3]) { //[
.................... dat[0] = '|';
0E5C: MOVLB 1
0E5E: MOVFF 1CC,FE9
0E62: MOVFF 1CD,FEA
0E66: MOVLW 7C
0E68: MOVWF FEF
.................... dat[1] = '?';
0E6A: MOVLW 01
0E6C: ADDWF xCC,W
0E6E: MOVWF FE9
0E70: MOVLW 00
0E72: ADDWFC xCD,W
0E74: MOVWF FEA
0E76: MOVLW 3F
0E78: MOVWF FEF
.................... dat[2] = '?';
0E7A: MOVLW 02
0E7C: ADDWF xCC,W
0E7E: MOVWF FE9
0E80: MOVLW 00
0E82: ADDWFC xCD,W
0E84: MOVWF FEA
0E86: MOVLW 3F
0E88: MOVWF FEF
.................... } //]
0E8A: MOVLB 0
0E8C: GOTO 124A (RETURN)
.................... tx[1] = '@';
1222: MOVLW 40
1224: MOVWF xCA
.................... tx[2] = '!';
1226: MOVLW 21
1228: MOVWF xCB
.................... tx[3] = '@';
122A: MOVLW 40
122C: MOVWF xCC
.................... ddOverWr(ddObjPtr(), &tx[1]);
122E: RCALL 0D1A
1230: MOVFF 02,1C9
1234: MOVFF 01,1C8
1238: MOVFF 02,1CB
123C: MOVFF 01,1CA
1240: MOVLW CA
1242: MOVLB 1
1244: MOVWF xCC
1246: MOVLB 0
1248: BRA 0E5C
|
2nd notation:
Code: |
.................... void ddOverWr(tDd* p, char* dat) { //[
.................... dat[0] = '|';
0E5C: MOVLB 1
0E5E: MOVFF 1CC,FE9
0E62: MOVFF 1CD,FEA
0E66: MOVLW 7C
0E68: MOVWF FEF
.................... dat[1] = '?';
0E6A: MOVLW 01
0E6C: ADDWF xCC,W
0E6E: MOVWF FE9
0E70: MOVLW 00
0E72: ADDWFC xCD,W
0E74: MOVWF FEA
0E76: MOVLW 3F
0E78: MOVWF FEF
.................... dat[2] = '?';
0E7A: MOVLW 02
0E7C: ADDWF xCC,W
0E7E: MOVWF FE9
0E80: MOVLW 00
0E82: ADDWFC xCD,W
0E84: MOVWF FEA
0E86: MOVLW 3F
0E88: MOVWF FEF
.................... } //]
0E8A: MOVLB 0
0E8C: GOTO 124C (RETURN)
.................... tx[1] = '@';
1222: MOVLW 40
1224: MOVWF xCA
.................... tx[2] = '!';
1226: MOVLW 21
1228: MOVWF xCB
.................... tx[3] = '@';
122A: MOVLW 40
122C: MOVWF xCC
.................... ddOverWr(ddObjPtr(), &tx[1]);
122E: RCALL 0D1A
1230: MOVFF 02,1C9
1234: MOVFF 01,1C8
1238: MOVFF 02,1CB
123C: MOVFF 01,1CA
1240: MOVLB 1
1242: CLRF xCD
1244: MOVLW CA
1246: MOVWF xCC
1248: MOVLB 0
124A: BRA 0E5C
|
Last edited by ulg on Mon May 13, 2019 8:09 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon May 13, 2019 7:46 am |
|
|
Your two code posts are identical.
However the key thing is that C does not have any concept of passing the
size of an array. In C if you want to pass the size, you have to do this as a
separate variable, containing the size. Passing a size, is an extension
added in later variant languages like C++, and not part of C.
An array is always passed as a pointer. Nothing else. Just says where
in memory it's first element is. Passing 'by value' is not supported. So
if you pass an array to a function and then modify an element, the
original array is changed. |
|
|
ulg
Joined: 09 May 2019 Posts: 24
|
|
Posted: Mon May 13, 2019 8:14 am |
|
|
Sorry - I've made a mistake when copying 2nd version (copied from wrong file or ctrl-C hasn't worked) - I've corrected it.
The called function will be compiled to same code for both notations, but the calling code will differ. The second one works.
1240: MOVLW CA
1242: MOVLB 1
1244: MOVWF xCC
1246: MOVLB 0
1248: BRA 0E5C
vs
1240: MOVLB 1
1242: CLRF xCD
1244: MOVLW CA
1246: MOVWF xCC
1248: MOVLB 0
124A: BRA 0E5C |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon May 13, 2019 8:30 am |
|
|
Since the second one is the correct notation, it is not surprising....
As I said, C does not support passing an array with a size.
You can use:
void ddOverWr(tDd* p, char dat[]) {
or
void ddOverWr(tDd* p, char* dat) { |
|
|
ulg
Joined: 09 May 2019 Posts: 24
|
|
Posted: Mon May 13, 2019 9:15 am |
|
|
Of course I do not pass the size of an array with 1st notation, but I give a hint to the compiler to report any try to access elements above 2 to be an error - aside from this hint, both notations should be the same.
Therefore, when I add the line
dat[3] = '*';
to the called function, the program will be compiled without any error with 2nd notation while the compiler reports an "subscript out of range" with 1st notation as CCS 3.249 does. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon May 13, 2019 10:16 am |
|
|
The point is that passing a size, is _not legal_ in C. The first notation
is just 'wrong'. The idea of limit checking is not a feature in C. Arrays don't
have sizes. This has been added to many later languages, but is not part of
C. Hence it doesn't work. |
|
|
ulg
Joined: 09 May 2019 Posts: 24
|
|
Posted: Mon May 13, 2019 11:25 am |
|
|
In my view all three notations
void ddOverWr(tDd* p, char dat[3])
void ddOverWr(tDd* p, char* dat)
void ddOverWr(tDd* p, char dat[])
are legal C, otherwise the compiler would report an error.
At all three notations the array parameter degrades to a pointer.
But only the first one offers the possibility to the compiler to report an error when accessing elements beyond element 2, if element number can be evaluated at compile time (e.g. with constant expressions), which CCS 3.249 does!
https://blog.feabhas.com/2013/11/shock-horror-i-learned-something-about-arrays-in-c/
Because the called function is compile to the same code for the first two notations (and I assume also for the third notation), my problem isn't located inside the called function, the problem arise on calling the function. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Mon May 13, 2019 11:32 am |
|
|
re:
are legal C, otherwise the compiler would report an error.
Maybe legal 'C' but not necessarily legal CCS 'C' ! There's probably 100+ variations of 'C' and NO version is 'cast in stone' as the ONE and ONLY version that must be used. K&R is the great,great grandfather though I believe even it 'evolved' over the years...... |
|
|
ulg
Joined: 09 May 2019 Posts: 24
|
|
Posted: Mon May 13, 2019 11:47 am |
|
|
It seems to be legal CCS 'C' too, because CCS 'C' doesn't report an error, when using "char dat[3]" notation - furthermore it uses the information given with the "3" to report a "subscript out of range" error, when I acccess e.g. dat[3] inside the called function (of course only when using "char dat[3]" notation). |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Mon May 13, 2019 2:04 pm |
|
|
No.
The reason it doesn't report an error, is that a size is both required and
legal, when using a multi-dimensional array. The compiler is not smart
enough to realise that the value here is not wanted.
It is actually an 'optional extension' in C99. But 3.249, is basically
pure K&R C, not C99.
It is not used as a size check declared as shown. Like this it is purely
for documentation (to tell the person reading the code how large the
array is expected to be). To be used as a size check, the keyword 'static'
has to be added.
However in both forms it is not part of CCS C. |
|
|
ulg
Joined: 09 May 2019 Posts: 24
|
|
Posted: Tue May 14, 2019 3:43 am |
|
|
Ok - that is understandable
I have just identified the third, for me unusual behavior of the CCS compiler - it doesn't support assignments of structs (and doesn't report any errors) - I have to do component-wise copying of structs, otherwise my prgramm fails.
Code: |
//p->fifo[p->wrIdx] = *msg;
p->fifo[p->wrIdx].typ = msg->typ;
p->fifo[p->wrIdx].val = msg->val;
//*msg = p->fifo[p->rdIdx];
msg->typ = p->fifo[p->rdIdx].typ;
msg->val = p->fifo[p->rdIdx].val;
|
It would be helpful to have a list of the pitfalls of that compiler - does anyone know, if something like this exists? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19515
|
|
Posted: Tue May 14, 2019 4:02 am |
|
|
Seriously, you are using a fourteen year old compiler version.
99.999% of your problems are from this.
There were historical issues with complex constructions such as references
inside references many years ago. It looks as if you are hitting this. |
|
|
ulg
Joined: 09 May 2019 Posts: 24
|
|
Posted: Tue May 14, 2019 4:29 am |
|
|
I have to do some minor extension to a product developed in the years after 2002. To avoid complex testing of different software versions on different hardware versions for different customers, I refrain from porting this software to MPLAB X. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Tue May 14, 2019 5:14 am |
|
|
You don't need MPLAB X, you need a newer version of the CCS C Compiler. I use both PCM and PCH compilers 'through' MPLAB v8.92 to program PICs .Have done for 20+ years, starting with PCM v2.43. Over the years I've used 4.xxx and 5.0xx versions using MPLAB 8.92 and can program PICs just fine.
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue May 14, 2019 11:41 am |
|
|
ulg wrote: |
It would be helpful to have a list of the pitfalls of that compiler - does anyone know, if something like this exists? |
Here is a list for PCH vs. 4.140, put together by a forum member in 2013:
http://www.ccsinfo.com/forum/viewtopic.php?t=50289 |
|
|
|