How do I pass an array to a function?

I'm hacking the melody example from here: http://arduino.cc/en/Tutorial/Tone

I am trying to play several different melodies so I want to pass them to a function to play. The arrays are showing up with len = 2 inside the playTune function. I'm a javascript programmer so I'm sure this is a C++ syntax issue, especially since I don't understand how you can have an int array full of char data.

Thanks in advance for sharing your wisdom.

#include "pitches.h"

int speakerPin = 12;
int baseSpeed = 600;

int horserace_notes[] = {
C4,F4,A4,C5,C5,C5,C5,0,A4,A4,A4,A4,0,F4,A4,F4,C4};
int horserace_beats[] = {
4, 4, 4, 4, 8, 8, 8, 8, 4, 8,8, 8, 8, 4, 4, 4, 2 };

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

playTune(horserace_notes,horserace_beats);
}

void loop() {
// no need to repeat the melody.
}

void playTune(int notes[], int beats[]) {

int len = sizeof(beats)/ sizeof(int);
Serial.print(sizeof(beats));

// iterate over the notes of the melody:
for (int thisNote = 0; thisNote < len; thisNote++) {

// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = baseSpeed/beats[thisNote];
tone(12, notes[thisNote],noteDuration);

// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
}
}

Here's a clue:

http://arduino.cc/en/Reference/Pointer

Welcome to C...

;D

The exact text:

Pointers are one of the more complicated subjects for beginners in learning C, and it is possible to write the vast majority of Arduino sketches without ever encountering pointers. However for manipulating certain data structures, the use of pointers can simplify the code, and and knowledge of manipulating pointers is handy to have in one's toolkit.

How do I use them?

I'm sorry, I've already searched the forums and google to try to resolve this myself. I wouldn't be posting here otherwise.

Actually, there might be a way around this without using pointers, its just that for array referencing/dereferencing in C, you typically see pointers used.

Maybe somebody has a better solution; I was being somewhat flip.

Essentially, though, you use the two operators to instead of passing the array, you pass the address-of the array, then inside the function de-reference that address to get the array starting point again, manipulate it (and change it if you want - even if out-of-scope, which is what makes pointers in C/C++ break the object model to an extent).

I'm so rusty on it, I couldn't give you an example to save my life!

;D

Here is a tutorial, though, on pointers (general C - not AVR):

http://pw1.netcom.com/~tjensen/ptr/pointers.htm

Good luck...

:slight_smile:

Here's some more:

http://boredzo.org/pointers/

Just google "c pointers", and you'll come up with more; the links I gave you were the top 3...

:slight_smile:

Thanks much for the help. I've tried a few different options and none of them seem to work. I think the problem is the int array holding char data but I don't know for sure. I don't understand how that worked in the first place so it's hard to troubleshoot. If anyone has any specific advice for this situation I would appreciate it greatly!

You need to pass a pointer (as mentioned above) to the array to your function. Then inside your function you do something like:

function do_something(char* my_array) {
  for (i = 0; i < 8; i++) {
    my_array[i];
  }
}

Where 8 is the number of elements in your array

The problem here is that whenever you pass an array to a function, it just passes a pointer to the beginning of the array. Inside the function, you can treat that pointer as a pointer, or you can treat it as an array, which is a kind of read-only pointer.

sizeof() is not a function. It is not calculated when your program runs. It is calculated by the compiler when your program is compiled. The compiler looks at the array you declared and substitutes the number of bytes in the array for the sizeof().

If you try to do a sizeof() on the pointer passed into a function, it will just return the size of a pointer, which is two bytes. If you understand that sizeof() is calculated when the program is compiled, not when it runs, then this makes sense. You could call the function from ten different places, with ten different arrays. The compiler can't know which array the function will be called with, so it can't know which array you want to know the size of.

The solution is to call the function with the array and the size of the array:

char my_array[] = {'a', 'b', 'c'};

loop()
{
  my_function(my_array,sizeof(my_array));
}

void
my_function(char a[],unsigned int a_size)
{
 for (int i = 0; i < a_size; i++)
    Serial.println(a[i]);
}

Regards,

-Mike

That makes perfect sense! It works now. Thank you very much.

Would you mind explaining how I can put characters into an int array now? That still seems very strange to me.

how I can put characters into an int array now

You mean like int myArray [] = {'a', 's', 'd', 'f'};?

Yes. My question is how does that work? int and char are 2 different things. I would expect an int array to hold only integer values, not characters like in my example:

int horserace_notes[] = {
C4,F4,A4,C5,C5,C5,C5,0,A4,A4,A4,A4,0,F4,A4,F4,C4};

C4 F4 etc are not characters, or strings, they're constants, either defined like:
#define C4 436
(which is a macro, so all ocurences of C4 in your code are replaced with 436)
or like:
const int C4=436;

(or whatever the value of C4 is)

They'll be in "Tone.h" I should think, if you want to see them.

A character constant has single quotes, thus 'C4' (yes, it is legal and fits in an int, if a little obscure), and a string constant has double quotes thus "C4", which occupies three bytes, including the implied null terminator.