Return multiple variables

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey
I have a quick question
I need to return more than one variable from a function..
normally I just use
return xxx;

but what can I do when I have both X and Y now ?

I'm programming in C

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

three approaches:

1. pass the address of each variable as parameters.
the function directly alters the variable.
e.g. the way that scanf() receives its values.
e.g. function(&X, &Y);

2. create a struct that contains multiple members.
return a pointer to this static struct.
e.g. struct X_Y *function(void);
struct X_Y *struct_ptr = function();

3. you are probably doing several operations on common group of variables. create a struct that contains them. Just pass the address of the struct to the function. The function directly alters the struct members.
e.g. struct A_B_X_Y group; // global struct
function(&group); // process struct

Conventional functions are 'called by value' and your variables are never directly changed by the function.
Once you start 'calling by reference' e.g. (1) and (3). You risk corrupting variables if you are not careful. C gives you all the rope to hang yourself with.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

let me just check if I get what youre saying here :)

1)

int x, y = 1;
Do_Somthing_Using_X_And_Y(&x,&y);

so here inside the function I just use the x and y from the main program ?

2) could you show an example as I'm not that good at struct or pointers yet :( (sorry)

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

so here inside the function I just use the x and y from the main program ?

Yes, for example:

void Do_Somthing_Using_X_And_Y(int * x, int * y) {
  *x = *y * 3;
  *y = *x + 2;
}

2)

typedef struct {
  int x:
  int y;
} ret_type;

ret_type * Do_Somthing_Using_X_And_Y(int x, int y) {
  static ret_type ret_struct;

  ret_struct.x = y * 3;
  ret_struct.y = x + 2;

  return &ret_struct;
}

3)

typedef struct {
  int x:
  int y;
} global_type;

gobal_type global_struct;

global_struct.x = 17;
global_struct.y = 5;
Do_Somthing_Using_X_And_Y(&gobal_struct);

...

void Do_Somthing_Using_X_And_Y(global_type * st) {
  st->x = st->y * 3;
  st->y = st->x + 2;
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

okay cool, helps a lot

can i do the same thing as in 2) just with arrays if thats better for the situation ?

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, Cliff. Excellent illustrations.

Method (2) is ok for a small 'composite' group of variables. e.g. two or three ints. It is not very suitable for larger structs.

If you want to do things to an array, you normally pass the address of the array to your function. e.g. method (3)

What exactly do you want to do?

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

right now I just like to learn more :)

but my problem is:
I have a large array with all the bytes which describes different letters on a LED matrix where each bit is a pixel.

I then made a switch case
where I ex. writes
get_sign('A');

then it will return the start bytes location in the big array and length/numbers of byte the letter "A" requires in this example
for short, it returns 2 bytes right now, or its supposed to do that

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can you show the actual data array - maybe just 'A', 'B', 'C'?

(if it's not fixed 8x8 matrices then I assume it's an array of struct{} in fact where each entry has the length then the data bytes)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
const uint8_t signs[] PROGMEM =
{

//A
0b00011110,
0b00000101,
0b00011110,

//B
0b00011111,
0b00010101,
0b00001010,

//C
0b00001110,
0b00010001,
0b00010001,
uint8_t find_sign_byte(uint8_t sign)
{
	switch(sign)
	{
		case 'A':
		sign = 0;	
		break;
		case 'B':
		sign = 3;	
		break;
		case 'C':
		sign = 6;	
		break;
}
	return sign
};

its the last function which needs to ALSO return the lenght of the signs, as ex. "." or ":" dosnt need to take up 3 spaces as the letters on my display(LED matrix)

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why do this with switch()/case? One option would be a second array with the offsets:

uint16_t offsets[] PROGMEM = {
  0, 3, 6, 8, 10, 13
};

typedef struct {
  uint8_t * data_addr;
  uint8_t len;
} c_data_type;

c_data_type * find_char(uint8_t c) {
  static c_data_type c_data;

  c_data.data_addr = &signs[offsets[c]];
  c_data.len = offsets[c+1] - offsets[c];

  return c_data;
}

Or as an alternative, embed the lengths into the pixel data array and treat is almost like a linked list where for each character you just add the offset to get to the next length field until you have incremented to the character you are looking for.

A separate offsets[] array effectively gives you "random access" while embedded lengths would be "sequential access". The advantage of all data in a single array is that you don't have to maintain two arrays and keep them in step as characters are added/removed.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

if I had a offset array.. how would you then find the offset for e.g. 'Y' ?
cant see how this can be done more effective than the switch :-/

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well I assume you have at least A..Z and possibly all the visible ASCII characters from 0x20 to 0x7F? But lets say you just had 'A' to 'Z'. They have ASCII values 0x41 to 0x5A. So if you just had the data for these characters you could index the arrays using the character number minus 0x41. Array element 0 would be 'A', array element 1 would be 'B' up to array element 25 for 'Z'. If you wanted 'M' (the 13th letter of the alphabet) you'd simply start by looking up offsets[12] which then gives you the offset into signs[] of where the 'M' data is located.

This obviously relies on you having an unbroken sequence of character patterns from ASCII 0xMM to 0xNN. You then subtract 0xMM to give a 0 based index.

If you have "sparse" data (like you only have A,B,C then L,M,N then you'd need some additional indexing. One way would be to put ALL the data together:

uint8_t all[] PROGMEM = {
 'A',
 3,
 0b00011110, 
 0b00000101, 
 0b00011110,

 'B',
 3,
 0b00011111, 
 0b00010101, 
 0b00001010,
...
 'L',
 4,
 0b00100111,
 0b10101010,
 0b01010101,
 0b11110000
...

You now start at all[0] and compare that with the character you are looking for. If it's 'A' then all[0+1] has the number of bytes and all[0+2]..all[0+2+len] has the data. If it's not 'A' you are looking for you add the byte after all[0] (the length) onto the index. Next char is at all[current + all[current+1] + 2] (where +2 skips the character and the length bytes). This does, because it involves sequential access, mean it takes much longer for you to find 'Z' than it does for you to find 'A'.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

that actually pretty nice :D
but for now a little to complex for me
but gives a good insight of how to use tables to lookup stuff

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson:
I will try your idea... I can see on the list, that I'll using almost everyone from 0x22 to 0x5A
:)
The idea is awesome, really :D
Like the way real programmers finds solutions :)

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There are (free) font generators that can generate a .h file with all your letters in a format like this for a 8x8 font:


...
0x00,0x00,0x64,0x92,0xF2,0x82,0x7C,0x00, // --> @
0x00,0x7C,0x7E,0x11,0x11,0x7E,0x7C,0x00, // --> A
0x00,0x7F,0x7F,0x49,0x49,0x4E,0x30,0x00, // --> B
0x00,0x1C,0x3E,0x63,0x41,0x63,0x22,0x00, // --> C
0x00,0x7F,0x7F,0x41,0x41,0x3E,0x1C,0x00, // --> D
0x00,0x7F,0x7F,0x49,0x49,0x49,0x41,0x00, // --> E
0x00,0x7F,0x7F,0x09,0x09,0x09,0x01,0x00, // --> F
0x1C,0x3E,0x41,0x49,0x79,0x38,0x00,0x00, // --> G
...

for the winavr you just need to at the progmem part.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have an even more human readable way of doing fonts...

Attachment(s): 

Imagecraft compiler user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But do you care as long you don't have to make the data by hand :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
There are (free) font generators that can generate a .h file with all your letters in a format like this for a 8x8 font:


...
0x00,0x00,0x64,0x92,0xF2,0x82,0x7C,0x00, // --> @
0x00,0x7C,0x7E,0x11,0x11,0x7E,0x7C,0x00, // --> A
0x00,0x7F,0x7F,0x49,0x49,0x4E,0x30,0x00, // --> B
0x00,0x1C,0x3E,0x63,0x41,0x63,0x22,0x00, // --> C
0x00,0x7F,0x7F,0x41,0x41,0x3E,0x1C,0x00, // --> D
0x00,0x7F,0x7F,0x49,0x49,0x49,0x41,0x00, // --> E
0x00,0x7F,0x7F,0x09,0x09,0x09,0x01,0x00, // --> F
0x1C,0x3E,0x41,0x49,0x79,0x38,0x00,0x00, // --> G
...


Could you link to one of these generators ?
for the winavr you just need to at the progmem part.

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I just checked the one I have used (a link from this forum) is dead ended (træls!), so try google, or somebody help, I will not be at the computer today!

Have fun

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This one has a lot of options, and it's free. I used it a couple of times ..
http://www.angelcode.com/product...

"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it"

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ahrg "Bitmap Font Generator" I just needed the right search word ;) thx

uC's: Atmega16, 32, 64, 128 and Attiny13
Lang.: C
Interests: Small scale robots AND sensor monitoring system