|
|
View previous topic :: View next topic |
Author |
Message |
Requan
Joined: 11 May 2008 Posts: 74
|
Call function with array as parameter |
Posted: Tue May 22, 2012 7:45 am |
|
|
Hi,
I'd like to call function with array as parameter.
To do it i used reference:
Code: |
void MyFunction(int8 Pointer)
{
for (;Pointer<Pointer + 5;Pointer++)
{
Singlvale =* Pointer;
}
}
void main()
{
BYTE MyArray[5] = {5,4,7,9,6};
int8* Pointer;
Pointer = MyArray;
MyFunction(Pointer);
while(1);
}
|
Could You tell me if it ok?
How to update array in MyFunction (by use &)? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Tue May 22, 2012 8:43 am |
|
|
The declaration in the function, needs to say that the value being passed, is a pointer, or an array, so:
Code: |
void MyFuction(int8 * Pointer) {
//or
void MyFunction(int8 Pointer[]) {
|
Then, your 'for' loop won't work, since you are incrementing 'Pointer' itself, how can Pointer ever get equal to Pointer+5?. You need to use a separate local value:
Code: |
int8 * StartingVal;
StartingVal=Pointer;
for (;Pointer<StartingVal + 5;Pointer++) {
Singlvale =* Pointer;
}
//or
int8 index;
for (index=0;index<5;index++) {
Singlvale = Pointer[index];
}
|
How to update in the function
*Pointer = val;
Will put 'val' into 'MyArray[0]'
or
Pointer[index] = val;
Will put 'val' into 'MyArray[index]'.
Since you are passing the pointer, the values addressed are the ones in the original 'main' function.
This is all 'standard C'.
Best Wishes |
|
|
Requan
Joined: 11 May 2008 Posts: 74
|
|
Posted: Tue May 22, 2012 11:17 am |
|
|
Ttelmah
Thank again for Your good explanation.
Please forgive me, but could You answer me on my one stupid question?:
Could You explain me when we use &?
Best Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Tue May 22, 2012 12:05 pm |
|
|
To get the address of something.
Imagine your main program had a larger array (say 30 elements), and you wanted the routine to do whatever you want with five elements from this. To do it with the first five elements, you can use 'Pointer=MyArray', and Pointer then contains the address of the first element in the array (the name of an array is a 'shortcut' for &MyArray[0]). However if you wanted to pass the address of the tenth element to the function, you instead use &MyArray[9].
Similarly, for other things than arrays,there is no shortcut to the address, so if you wanted to pass the address of a float value, for example, then you use &floatval to get the address. Remember also that you can do some perhaps unexpected things by mixing types. For instance:
Code: |
int xorb(int8 * ptr, int8 nbytes) {
int8 count;
int8 total=0;
for (count=0;count<nbytes;count++) {
total^=ptr[count];
return total;
}
void main(void) {
float val=123.45;
int8 bytexor;
bytexor=xorb(&val,4);
printf("The 8bit xor of the bytes in the float 123.45 is %d\n\r",bytexor);
do {
} while(TRUE);
}
|
The code takes the address of the float value, and the 'count' of the number of bytes in the float (4), then treats the address as if it points to an int8, and xor's the 4 bytes together, and returns this.
Best Wishes |
|
|
Requan
Joined: 11 May 2008 Posts: 74
|
|
Posted: Wed May 23, 2012 1:26 am |
|
|
Ttelmah
I run Your second method (Pic18F67J60, compiler 4.132):
Code: |
void MyFunction (int8 Pointer[])
{
int8 index;
int8 val = 0;
for (index = 0; index<5; index++)
{
val = Pointer[index];
}
}
void main()
{
BYTE MyArray[5] = {5,4,7,9,6};
int8 *Pointer;
Pointer = MyArray;
MyFunction (Pointer);
}
|
and in val I had (5, 7,6), instead (5,4,7,9,6) and I don't understand why.
G\ Could You also explain why we call: MyFunction (Pointer); instead MyFunction (&Pointer); - & is a address and we call fuction with address of MyArray. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Wed May 23, 2012 1:43 am |
|
|
I really suggest you get a basic C book....
However have already answered one part, with:
"the name of an array is a 'shortcut' for &MyArray[0]"
Now, the 5,7,6 thing, should not be happening if the code is exactly as posted. However would be happening, if the compiler thinks at some point you are talking to an int16. One possibility is that you have found a bug in the pointer handling in 4.132.
This is where the 'basic book' thing comes in. Pointers and arrays are quite complex. In C, if you have a pointer to an array of int8 objects, or an array, and you increment the array index, or the pointer, the 'target' moves forward by one byte. However if the pointer is to int16 objects, then the target moves forward by two bytes. Pointer arithmetic, and array indexes always work in the 'size' of the object addressed.
Best Wishes |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed May 23, 2012 9:18 am |
|
|
CCS C doesn't like your pointer definition (although it should work as well)
Code: | void MyFunction (int8 Pointer[]) |
Use standard C syntax and everything is right
Code: | void MyFunction (int8 *Pointer) |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Wed May 23, 2012 11:22 am |
|
|
FvM wrote: | CCS C doesn't like your pointer definition (although it should work as well)
Code: | void MyFunction (int8 Pointer[]) |
Use standard C syntax and everything is right
Code: | void MyFunction (int8 *Pointer) |
|
Except both are 'standard C'....
Page 100 in K&R second edition, says:
" char s[];
and
char *s;
are equivalent"
Page 95 in the first edition is even more explicit, saying they 'are exactly equivalent'.
I must admit I'd normally use the 'pointer' declaration, even if latter I access the elements as an array, but both are equally 'standard' declarations, and work OK on most CCS versions, and on every other compiler...
Looks like a bug in 4.132.
Best Wishes |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Wed May 23, 2012 11:24 pm |
|
|
Quote: | Except both are 'standard C'.... |
No doubt they they are. I should have written, the "commonly used C pointer syntax".
Quote: | both are equally 'standard' declarations, and work OK on most CCS versions, and on every other compiler... | In fact it's a new CCS C bug, introduced between V4.128 and V4.132. The case illustrates why it's probably
better to restrict yourself to a "commonly used" C subset with CCS C ... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Thu May 24, 2012 1:35 am |
|
|
Yes.
I must admit as I said I'd normally use the pointer syntax, and tend to reserve the 'array' syntax, for when passing multi-dimensional arrays, where it can make coding clearer. I used the array syntax here, since it looked to make it slightly plainer that you can use arrays inside the subroutine, just as easily as pointers. In many C versions, the pointers are quicker (which is why they are often preferred), but in CCS this isn't the case. Key is to understand that when you pass a pointer, you can access the elements in the subroutine, either using pointers or as an array (or both).
The last time I used that syntax 'for real' was with about 4.118, and it is so fundamental, I didn't expect CCS to get it wrong here. It is quite an interesting bug, since they appear to be treating the pointer passed as if it addresses an int16, when the array syntax is used, but are returning an int8.
Also though, a classic 'warning' about CCS, treat all new compilers as 'beta'. The idea that upgrading to the latest is 'good', is something that has to be thrown away when using CCS C.....
Best Wishes |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Thu May 24, 2012 2:21 am |
|
|
Remember that in C arrays and pointers are very closely related. Indeed pointers appear to have been introduced primarily as a efficient means of accessing array elements. In C the array name IS a pointer to the start of the array elements. That means "&Array[0]" is the same as "Array", and as a parameter, "int Array[]" is the same as "int *Array".
It may be the moment to resurrect the discussion about the placement of the * in C syntax. Oddly in C, "*" is a modifier of the variable, not of the type. You may see people write "int* P", menaing a integer pointer named P. That works. It works just the same as "int *P" meaning a pointer named P to an integer. C allows both, but "int *P" is the syntactically more "correct" version. Don't expect "int* P, Q" to work as you might expect: i.e. two pointers, called P and Q, to int. It has to be "int *P, *Q", or perhaps rather confusingly, "int* P, *Q".
While that works with C++, don't try that with C#! C# has done away with C style pointers almost totally. It has the related, but differently implemented reference construct instead.
In C pointers are basically little more than memory addresses. Indeed in C "void *P" IS simply an address into (untyped) memory. This made sense in the computing world from which C was born. There was generally a simple and direct relationship between variables and memory. In today's hardware abstracted, virtualised computing world that relationship doesn't hold true anymore in many processing environments, making C a relatively poor fit to many of today's processors. It DOES still hold for simple processors such as the PIC.
Technically C does not allow the passing of arrays as parameters. You can pass pointers to arrays, or to array elements, but these are similar to references and allow changing of the parameter. In other languages, you would have to specifically signal this was the case by "var", "ref" or some such some syntactic means. In C non arrays are passed by value by default, in other words the value of the varaible is given to the function, and the function cannot change the variable itself, But in C an array is a pointer, so "passing an array" as a parameter means passing a pointer, allowing full access, write and well as read, to the array.
Generally I like to make it clear when I intend to pass a pointer and when an array, and use the syntax to make that apparent. I don't like to mix the paradigms. I also make it clear when I am dealing with pointers to potentially variable types. For example when I've got a comms protocol that sends messages, I then have some access routine that interprets the data for a message which deals with the type conversions into int8s, int16, strings and whatever by casting from the data in the message pointed to by a byte pointer.
So, perhaps what worries me most about the original post is the mixing of data types and pointers to them. In CCS C int8 and byte happens to be the same. Just happens. A atrongly typed language, such as C# would not allow you to mix types like this. Its a bad habit to get into. It appears it can also confuse compilers of little brain such as CCS, though to be frank mixing types like that is simply asking for trouble.
RF Developer |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19510
|
|
Posted: Thu May 24, 2012 2:55 am |
|
|
The original post, wouldn't work at all.
He was passing a pointer, then telling the function he was passing an int8. Not useable _anywhere_.
Best Wishes |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu May 24, 2012 4:28 am |
|
|
Quote: | In CCS C int8 and byte happens to be the same. |
Strictly spoken, none of the types is defined in a C standard include file. std_int.h e.g. has int8_t and uint8_t. As we all know, the usage of int and int8 for unsigned quantities in CCS 8 bit compilers is different from what the C standard suggests. byte or BYTE is used in a number of C compilers for an "uint8_t", but non-standard, too. |
|
|
|
|
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
|