Pages: [1] 2   Go Down
Author Topic: How can I return a 12 byte from a function?  (Read 981 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Need some help...
I am getting a 12 byte data from SPI interface.

I got a function for read register, want to store 12 byte in "result",
then return it when this function ends.
Is it possible?
Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3352
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Declare an array that can store the 12 elements. Pass the array to the function. Pack the data into the Array.
Logged

Offline Offline
Sr. Member
****
Karma: 25
Posts: 498
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Use a global data area.  Declare a global array of 12 bytes.  Not what you asked, but it would do the job.

If you really want to return 12 bytes, you could pass 3 long ints by reference.
Logged

California
Offline Offline
Faraday Member
**
Karma: 88
Posts: 3352
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you really want to return 12 bytes, you could pass 3 long ints by reference.
.. or just pass an array of 12 bytes.
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
struct mydatas {
  char data[12];
};
mydatas f();

void setup() {
  mydatas foo = f();
}
void loop() {}

mydatas f() {
  mydatas myd;
  myd.data[4] = 4;
  return myd;
}
Logged

Cincinnati, OH
Online Online
God Member
*****
Karma: 40
Posts: 673
I'm not bossy...I just know what you should be doing.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

WisenedEE code probably meant the line to be:

Code:
  myd.data[4] = '4';

since it is a character array. If the purpose of the function is to change the 12 bytes in some way, yet not use global scope for the data, why not use:

Code:
void setup() {

  Serial.begin(9600);
 
}
void loop() {
  char data[12];
  f(data);
 
  Serial.println(data[4]);

}

void f(char c[]) {
 
  c[4] = '4';

}
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

WisenedEE code probably meant the line to be:

Code:
  myd.data[4] = '4';

since it is a character array.
No, char is just the standard one byte type. So a char array of length n is universally known to be 12 bytes.
Logged

Cincinnati, OH
Online Online
God Member
*****
Karma: 40
Posts: 673
I'm not bossy...I just know what you should be doing.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I misunderstood what you were trying to do.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I misunderstood what you were trying to do.
Weren't the comments clear enough?  smiley
Logged

Cincinnati, OH
Online Online
God Member
*****
Karma: 40
Posts: 673
I'm not bossy...I just know what you should be doing.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

PaulS: good point! smiley-lol

This is a perfect example of what I call a silent cast. Anytime the data type for the expression on the right side of the assignment operator can fit the data type on the left side of the expression, there is no complaint from the compiler, as in the expression:
Code:
  myd.data[4] = 4;   // Silent cast
What the compiler is actually doing is:
Code:
  myd.data[4] = (char) 4;   // Documented cast
Although C and C++ do type checking, the compiler doesn't complain if it can figure things out on its own. Using the Bucket Analogy, the compiler barfs on
Code:
int i;
float x = 10.0;
i = x;   // Information could be lost
The assignment expression is a problem because you're trying to pour data from a 4 byte bucket into a 2 byte bucket, risking a loss of data. WisenedEE assignment works fine, but I didn't understand he wanted the compiler to do the cast. I think using an explicit cast is always better even if it's not needed as it better shows (i.e., documents) your intent. (I always dinged my students if they used a silent cast.)
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
This is a perfect example of what I call a silent cast.
C calls it an implicit cast. The compiler knows that a 4 byte value won't fit in a two byte memory location, so it generates a warning. The Arduino team has decided that it is not important to see that message.

The real problem, as I see it, it that WizenedEE's code is unnecessarily complicated. Reference variables were invented for just the purpose that OP wanted. Wrapping an array in a struct just so that a function can return a single address is useless overhead. Use a reference variable and pass the array address to the function.
Logged

Cincinnati, OH
Online Online
God Member
*****
Karma: 40
Posts: 673
I'm not bossy...I just know what you should be doing.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

PaulS: Exactly. That's why I suggested using a local array.

I was puzzled by WisenedEE statement:

No, char is just the standard one byte type. So a char array of length n is universally known to be 12 bytes.

because I didn't realize that an array length n is universally known to be 12. If you want to use a one byte type, why not define the array as a byte data type. Very confusing to me...
Logged

Mid-Atlantic, USA
Offline Offline
God Member
*****
Karma: 30
Posts: 514
"Remember kids, the only difference between Science and screwing around is writing it down." - Adam Savage
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

PaulS: Exactly. That's why I suggested using a local array.

I was puzzled by WisenedEE statement:

No, char is just the standard one byte type. So a char array of length n is universally known to be 12 bytes.

because I didn't realize that an array length n is universally known to be 12. If you want to use a one byte type, why not define the array as a byte data type. Very confusing to me...


This brings up a question to the OP...

@milkbottlec
 Are the individual bytes signed or unsigned values? Use data type byte if unsigned, char if signed. If mixed you may need a struct... And, if you are using any of the Stream based output methods, watch-out for the difference in how .print() handles byte vs char...
Logged


Heemskerk, Netherlands
Offline Offline
Sr. Member
****
Karma: 10
Posts: 356
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Maybe this is a suggestion:
Code:
// Do not remove the include below
#include "pointertest.h"


//The setup function is called once at startup of the sketch
char str[12];
char *ptr = &str[0];

void fptr(char *xptr){
for (int i=0; i <12; i++){
*xptr = char(i);
}
}
void setup()
{
// Add your initialization code here
char xstring[12];
char *yptr = &xstring[0];
fptr(yptr);

}

// The loop function is called in an endless loop
void loop()
{
//Add your repeated code here
fptr(ptr);
}

In this example str is a 12byte buffer
*ptr = a pointer to the first byte in the buffer
fptr is a function that rexieves a pointer. Al it does is start filling the buffer with 12 values.

Here setup calls the function and so does loop. both give fptr a pointer and the function starts filling the 12 bytes of that address given to it.
Logged

Offline Offline
Edison Member
*
Karma: 19
Posts: 1041
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

because I didn't realize that an array length n is universally known to be 12. If you want to use a one byte type, why not define the array as a byte data type. Very confusing to me...
Because byte is not standard C. char is the only standard C known-by-compiler one byte datatype. uint8_t is defined in stdint.h and byte is a nonportable arduinoism (although one I do like)
Quote from: Arduino.h
Code:
typedef uint8_t byte;
Quote from: stdint.h
Code:
typedef unsigned char uint8_t;

Quote
The real problem, as I see it, it that WizenedEE's code is unnecessarily complicated. Reference variables were invented for just the purpose that OP wanted. Wrapping an array in a struct just so that a function can return a single address is useless overhead. Use a reference variable and pass the array address to the function.
I understand and often use passing by reference but I don't really like it. It goes against the ideas of functional programming (passing by reference means there's side effects). It's also not great because defining a variable takes two lines: one to declare it and allocate space and another to call a function to fill it up with nice data. Of course, those are minor issues that people generally ignore. I was simply pointing out an alternative. Furthermore, the OP specifically asked for how to "return" 12 bytes. Of course, one could assume that the OP doesn't know what he/she needs which may be true, but it's hardly considered good form to berate someone for giving a solution to the literal question posted.

Quote
I misunderstood what you were trying to do.
I assumed it was assumed that people posting replies were trying to help the OP by posting solutions to their problems.

Quote
Maybe this is a suggestion:
Code:
pointertest.h: No such file or directory
Logged

Pages: [1] 2   Go Up
Jump to: