0

I want to converse data from long to bytes and vice versa. After searching around, I sticked together some code, which seems to work (the same code works for int and floats as well).

The long value LongVal changes to a byte array, and the four bytes construct LongVal2. Obviously LongVal = LongVal2.

long LongVal = -4080;
long LongVal2;

void setup(){
  Serial.begin(9600);
}

//byte* my_function(long LongVal){
//  byte *LongVal_byte = (byte *) & LongVal; 
//  return & (LongVal_byte[0]);
//}

//long my_function2(byte & LongVal_byte){
//  long LongVal2;
//  memcpy(&LongVal2, LongVal_byte, sizeof(LongVal2));
//  return  LongVal2;
//}

void loop(){

  byte *LongVal_byte = (byte *) & LongVal; 
  memcpy(&LongVal2, LongVal_byte, sizeof(LongVal2));
  Serial.println(LongVal2);  
  Serial.println(" ");  

//byte LongVal_byte = my_function(long LongVal);
//LongVal2 = my_function2(byte & LongVal_byte);  

}

But should I try to wrap the two first lines of loop() in two individual functions, errors occur. The remarked lines are my attempts to create two functions.

How to wrap them up properly?

EDIT This is what appears if I try to use the remarked functions:

 In function 'long int my_function2(byte&)':
15:51: error: invalid conversion from 'byte {aka unsigned char}' to 'const void*' [-fpermissive]
25:0,
1:
117:14: error:   initializing argument 2 of 'void* memcpy(void*, const void*, size_t)' [-fpermissive]

 In function 'void loop()':
26:33: error: expected primary-expression before 'long'
27:30: error: expected primary-expression before '&' token
4
  • And what do the "errors" say? Hint: they tell you what is wrong - they're not just printed for fun. Read them. They are generally self explanatory. – Majenko Jul 13 '16 at 19:47
  • @ Majenko That is true, but due to my inexperience to C, I lack to interpreter them. – user3060854 Jul 13 '16 at 19:52
  • But we can. Or we could if you told us what they were. By the way, I can already see some fundamental misunderstandings and mistakes in your code. I want to marry those up with the error messages you are getting so that you can understand the errors better in the future. – Majenko Jul 13 '16 at 20:01
  • @ Majenko I just added the error comments. – user3060854 Jul 13 '16 at 20:20
1

So many problems here:

1) in function call there shouldn't be types, only arguments. byte LongVal_byte = my_function(LongVal);

2) & before variable means "get variable address". However in function prototype long my_function2(byte & LongVal_byte) it means reference to passed variable (and it must be byte), not a pointer.

3) pointer to local variable is returned from my_function. It might be working until pointed memory gets rewrited by something else (another function call or so)

And whole code might look like that:

long LongVal = -4080;
long LongVal2;

void setup(){
  Serial.begin(9600);
}

byte * my_function(long & LongVal) {
  return (byte*)&LongVal;
}

long my_function2(byte * LongVal_byte) {
  return *((long *)LongVal_byte);
}

void loop(){

  byte * LongVal_byte = my_function(LongVal);
  LongVal2 = my_function2(LongVal_byte);  

  Serial.println(LongVal2);  
  Serial.println(" "); 
}

But it is basically exactly the same as before without functions (just no need for memcpy)

1
  • @ KIIV It works flawlessly, and even more, it works with every type of variables, (int, floats, even strings), providing that I set in the code the right type of variable. – user3060854 Jul 13 '16 at 21:12
1

15:51: error: invalid conversion from 'byte {aka unsigned char}' to 'const void*' [-fpermissive]

memcpy(&LongVal2, LongVal_byte, sizeof(LongVal2));

LongVal_byte is a single byte. It's not a pointer, and memcpy expects a pointer.

26:33: error: expected primary-expression before 'long'

byte LongVal_byte = my_function(long LongVal);

You do not specify the variable type when passing a variable to a function. The variable already knows what it is, and the function already knows what it wants.

27:30: error: expected primary-expression before '&' token

LongVal2 = my_function2(byte & LongVal_byte);  

Same there.

You are showing a fundamental lack of understanding of some concepts of C. Other errors you are making:

long LongVal2;
...
long my_function2(byte & LongVal_byte){
    long LongVal2;

You should never ever re-define a global variable inside a function. It's not actually syntactically incorrect, but from a reading perspective it becomes almost impossible to keep track of which LongVal2 variable is being used at any one time.

long my_function2(byte & LongVal_byte){

You are passing a reference to a single byte, not an array of bytes. For that you need a pointer.

You should re-write your functions to be like this:

byte* my_function(long LongVal) {
    return (byte *)&LongVal;
}

(although that is completely pointless, you just need to cast the value, you don't need a function to do it:

byte *byteval = (byte *)&LongVal;

)

long my_function2(byte *LongVal_byte){
    long LongVal2;
    memcpy(&LongVal2, LongVal_byte, sizeof(LongVal2));
    return LongVal2;
}

That is a long winded, but "safe" way of doing it. It is needed only on CPUs where alignment matters. On an 8-bit CPU the alignment is 8-bit, and so a 32-bit word can be at any address. On a 32-bit system a 32-bit word will be at a 4-byte alignment, so that method is needed. On an 8-bit though you can just cast the array into a long:

long *LongValue = (long *)&LongVal_byte;

A better solution to the whole thing, though, is to use a union:

typedef union {
    byte byteval[4];
    long longval;
} LongBytes;

LongBytes myVal;

You can then access:

myVal.longval = 4893723284;

And also:

myVal.byteval[i];

where i is 0-3.

1
  • @ Majenko Your comments were quite thorough and useful. Thank you for your interest. – user3060854 Jul 13 '16 at 21:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.