Passing byte arrays

Hi all,

I could not find an article explaining this matter decently so I decided to make one of myself. There are some decent articles on pointers and bytes in C, but nowhere could I find a proper guide on how to pass byte arrays copy their pointers.

The trick with arrays is that you don’t copy all the values but only the pointer to the first value in the array. If you have this pointer and you know the size of the array you have all the information to extract all the data from the array.

When you’re making a pointer byte A_ to a variable byte A you indicate that it is a pointer by using the __. To retrieve the pointer to said variable A, you can use the reference symbol &. For example, &A will return the pointer to A. All seems to be working fine as long as we’re not using arrays. But since arrays are passed by reference by default in C the use of the & is omitted. Also, this omitting of the & seems to be obligatory in C.

I have been playing around with this a long time today and ended up with code which turned out to work. It was only after that that I started to understand what was happening.

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

byte *msgPointer;
byte msg[4] = {1, 2, 3, 4};

void loop()
{
  pointAt(msg);

  for(int i = 0; i < 4; i++)
  {
    Serial.print(msgPointer[i]);
    Serial.print(" ");
  }
  Serial.println();
  for( ; ; );
}

void pointAt(byte msg[])
{
  msgPointer = msg;
}

The variable byte *msgPointer is thus a pointer as demonstrated by the *.

At first sight it be more practical to just declare it as byte msgPointer[] and then let it point to msg by doing *msgPointer = &msg (in fact we must omit the & since this is a must). But since we’re declaring byte msgPointer[] here as an actual array and not as a pointer it would certainly take up some space in the arduino memory. Especially when you declare the size of the array up front by putting a number in the []. “Just” having it point to another array would “release” the space this array is currently using and would not really make sense. That’s why we declare byte *msgPointer already as a pointer. Since passing arrays goes by reference automatically in C and msgPointer is already a pointer it’s a very simple operation of msgPointer = msg. After that we can easily acces the values of msg with the pointer msgPointer.

You can retrieve the values of msg by using msgPointer[ x ] where x is a valid index of msg. This syntax might be a little awkward at first, since you’re indexing a pointer, which is just a memory address and NOT the actual array itself. But if you think about it carefully, there is no real other logic syntax to do this.

I hope this helps you understand passing arrays and using pointers better. I’ve been messing with this all night and it almost made me give up. But this understanding helped me a lot in my project.

Cheers.

I find the syntax used in Arduino to do this a little bit confusing though.

Try not to think of it as Arduino's fault - blame Kernighan and Ritchie. (that's a hint to go and research C and C++)

(You may want to use some [nobbc][/nobbc] tags on your last post - the last paragraph got munged)

You better study up some more.

msg is constantly destroyed and recreated on the stack. It is fine in this toy example, but will fail badly if it is a function called from loop().

Why not just make the buffer global?

AWOL:
Try not to think of it as Arduino's fault

I won't haha. Now I've come to think about it, there is really no better way to syntax this. Except maybe not bitching about the &-sign and allowing to "re-point" an array which is still empty, that would be practical but would probably introduce other crap.

AWOL:
(You may want to use some [nobbc][/nobbc] tags on your last post - the last paragraph got munged)

Yep, thanks. I edited that now :).

KeithRB:
You better study up some more.

msg is constantly destroyed and recreated on the stack. It is fine in this toy example, but will fail badly if it is a function called from loop().

Why not just make the buffer global?

You're right but this code stops after one loop. In my actual project the msg buffer is indeed global. I shall edit that in my example code above.

Your copyByteArray() function does NOT copy anything. What you have when it is done, is two addresses pointing to the same data.

PaulS:
Your copyByteArray() function does NOT copy anything. What you have when it is done, is two addresses pointing to the same data.

Correct, I renamed it to pointAt(byte msg[]).

So, now I'm wondering why you need a function to do that.

PaulS:
So, now I'm wondering why you need a function to do that.

Basically you're right. But it is part of a bigger and complex whole.

Anteino:
I hope this helps you understand passing arrays and using pointers better. I’ve been messing with this all night and it almost made me give up. But this understanding helped me a lot in my project.

I used to understand pointers, then I read your post.

:confused:

I was wondering the same!

Anteino:
The trick with arrays is that you don't copy all the values but only the pointer to the first value in the array. If you have this pointer and you know the size of the array you have all the information to extract all the data from the array.

You can pass the entire array to a function, but it needs to be defined within a struct:

struct test {
  int array[4] = {1, 2, 3, 0};
  int val;
} myStruct;

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

void MyFunction(struct test s)
{
  int i = 0;
  while (s.array[i]) {
    Serial.println(s.array[i++]);
  }
  Serial.print("size of array is: ");
  Serial.println(sizeof(s.array));
}

void loop() {

}

You can pass the entire array to a function, but it needs to be defined within a struct:

You don't need to pass the array to the function. Just pass the pointer to the start of the array, and the length of the array (if that matters/varies).

A struct isn't passed by value.

PaulS:
You don't need to pass the array to the function. Just pass the pointer to the start of the array, and the length of the array (if that matters/varies).

A struct isn't passed by value.

@Paul. Yeah, I kinda knew that already. I was simply pointing out that the statement by the OP that you can't pass an array to a function is not completely true. It can be done by burying it in a structure, although I can't think of a reason why you'd want to do it. I also understand that it's a pointer that gets passed for the structure, but the array is passed, which is why I put the sizeof() operator in the code.

BulldogLowell:
I used to understand pointers, then I read your post.

:confused:

Sorry :stuck_out_tongue: Then forget the whole thing