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

Returning an array from a function....

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



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

Returning an array from a function....
PostPosted: Tue Mar 10, 2015 7:25 am     Reply with quote

Hi All,

I have a function that reads a temperature and humidity sensor. I'd like to return both values, possibly in an array, when the function is called, but I haven't been successful thus far....

Code:

int16 ReadSensor(void)
{
   int16 TH[2] = {0,0};
   .
   .
   .
   TH[0] = Humidity;
   TH[1] = Temperature;

   Return(TH);
}


Now, I'm trying to use the function like this:

Code:


   int16 Values[2];
   Values = ReadSensor();
   fprintf(Console, "Humidity = %ld%%\n\r", Values[0]);
   fprintf(Console, "Temperature = %ldC\n\r", Values[1]);



But this code won't compile. I've tried many variations, but it either won't compile, or the returned values are incorrect.

Can someone point me to the proper way to pass two variables back from a C function, and then read them?

Thanks,

Jack
temtronic



Joined: 01 Jul 2010
Posts: 9245
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Mar 10, 2015 7:34 am     Reply with quote

First you MUST post a small, compilable program ! Just displaying 'snippets' doesn't help us help you.

Generally speaking though a function can only return one value.

As far as what it 'looks' like you want, just declare the sensor variables as 'global', then your 'read sensor function' will put the results into a 'common' memory location where in 'main()' can read and display the results.

Unless you're really,really strapped for RAM, I don't any reason to do it the hard way....though it could be done, I suppose.

Jay
kWoody_uk



Joined: 29 Jan 2015
Posts: 47
Location: United Kingdom

View user's profile Send private message

PostPosted: Tue Mar 10, 2015 8:20 am     Reply with quote

If you make the array static it should work.

Or you could pass the address of the array into the function, and work with it that way.


Keith
Ttelmah



Joined: 11 Mar 2010
Posts: 19551

View user's profile Send private message

PostPosted: Tue Mar 10, 2015 9:15 am     Reply with quote

As posted it'll never work.

He is declaring the function to return an int16. TH, is the address of the array (but the array won't exist after the function exits - this is the point about declaring it as static), but even if it was static, the code needs to say that he is returning a pointer, not an integer.....
Then there is the inherent problem about this of 'knowing' the size of the returned object.
In C, things like 'sizeof', only work inside the function where a variable is declared. Better to declare a 'structure' outside the function (hence global), containing the array. Declare 'TH' in the function to be a structure of this type, and declare the function to return a pointer to such a structure. Then all the components will actually 'know' what is being passed. So:
Code:

//Different ways:
Typedef struct {int16 TH[2]} THtype;

THtype * ReadSensor(void)
{
  static THtype val;
  val.TH[0] = Humidity;
  val.TH[1] = Temperature;
  return &val;
}

//This then returns a pointer to the physical data stored in
//the static 'val' variable.

//In the main have a variable as:
    THtype * rval;
    rval=ReadSensor();
    temperature = rval->TH[0];
    //and the same for humidity

//Or
//With the same typedef
THtype ReadSensor(void)
{
  THtype val;
  val.TH[0] = Humidity;
  val.TH[1] = Temperature;
  return val;
}
//This then physically returns the value as a structure of THtype.

   THtype rval;
   rval=ReadSensor();
   temperature=rval.TH[0];
   //etc..

//Or
int16 * ReadSensor(void)
{
   static int16 TH[2] = {0,0};
   .
   .
   .
   TH[0] = Humidity;
   TH[1] = Temperature;

   Return(TH);
}   

   //then in the main
   int16 * rval;
   rval=ReadSensor();
   temperature=rval[0];
   //and again for humidity


I think I've typed these all right, but no guarantees....
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Tue Mar 10, 2015 10:20 am     Reply with quote

If its declared as a non-static local variable, then the variable doesn't exist outside of the function. You can pass a pointer to a local variable as the return value of a function, but the pointer has no meaning outside of the function. This might work in some cases, but don't bet on it.

If the variable is declared as a static local, then it does exist outside of the function (even though technically its out of scope). This means a pointer to it will point to something useful. However, the value pointed to should be considered volatile as it may change, and indeed will every time the function is called. Its okay if you only use values soon after calling the function, but if you expect them to still be there after a few calls... if you do, well, you won't get what you expect.

The way this would often be done is with dynamic memory: malloc a variable of the required type in the function and return a pointer to it. Its then up to the calling code to free the memory at some later stage. However, using dynamic memory on processors with such limited RAM as most PICS is fraught with problems and is rarely successful. In general its best avoided. As yet, I have not used dynamic memory in any of my PIC, or even ARM, code and I don't want to encourage its use. This is why I'm not giving an example of this technique.

I tend to call by reference: pass a pointer to the routine, pointing to a structure, array or union, which the function can fill with the required data. This is something like this. Note, you don't have to pass a pointer to a structure, you can pass a pointer to an array, or even an element of an array as many of the string (strings simply being arrays of char in C) and memory functions do:

Code:

Typedef struct {int16 TH[2]} THtype;

THtype Temperature;

void ReadSensor(THtype * Val)
{
  val->TH[0] = Humidity;
  val->TH[1] = Temperature
}

...

ReadSensor(&Temperature);
 
JAM2014



Joined: 24 Apr 2014
Posts: 138

View user's profile Send private message

PostPosted: Tue Mar 10, 2015 10:50 am     Reply with quote

Hi Guys,

Thanks for the suggestions! I'm pretty good with electronics, but I'm just beginning to learn the 'C' language, and I want to learn it the "proper" way. I'm in the process of updating a number of projects, originally done in assembler, with CCS 'C' code. This project is now working like a charm.

Thanks,

Jack
Ttelmah



Joined: 11 Mar 2010
Posts: 19551

View user's profile Send private message

PostPosted: Tue Mar 10, 2015 11:29 am     Reply with quote

I have to say that RF_developer is very right. It's always better to pass the variable 'to' the function, and return the values in this. This is the 'really right' way of doing it, but I was trying to just answer the 'how to return an array' part of the question, and ignoring this.

There is one other way that has been missed, which is to pass by reference.

This can be better for small functions that are 'in-lined'.
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