0

I am writing a small program that plays a song on a buzzer. I am creating a function that expects a two dimensional array. The array can contain unlimited rows and two coloumns. The first column contains a previously defined constant, which is the frequency of the note and the second is the length.

I googled how to pass an array to a function and I think I am doing as I read but for some reason the function does nothing. As I figured out adding some Serial.print() calls, I found out that the function sees a 0 length array.

//Definitons of frequencies and pinout and tempo

...

unsigned int mySong[][2]{

                      {G2, 2}, 
                      {B2, 1}, 
                      {D3, 1}, 
                      {G3, 2}

                    };

void playSong(unsigned int song[][2])
{
  Serial.println(sizeof(song)/sizeof(song[0]));

  for(int i = 0; i<sizeof(song)/sizeof(song[0]); i++)
  {
     tone(buzzerPin, song[i][0], (song[i][1]*tempo));
     Serial.println(song[i][0]);Serial.println(song[i][1]);
     delay(song[i][1]*tempo);
   }
}

void setup() {
  pinMode(buzzerPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  playSong(mySong);
}

But if I change every 'song' to 'mySong', it works fine and plays the music and the readings in the serial monitor are correct, so it suggests that the way I found out should be good, and the array and constants should also work fine, so the data gets lost when I am passing it to the function.

What may I be doing wrong?

Thanks in advance for any help.

2 Answers 2

2

When passing arrays as arguments to functions the arrays decays to pointers to their first element. So even when you write

void playSong(unsigned int song[][2])

the compiler will treat it as

void playSong(unsigned int (*song)[2])

That means that doing sizeof(song) will not work, as you then will get the size of the pointer and not the data it points to. You need to pass the first "dimension" as an argument as well:

void playSong(unsigned int song[][2], size_t num_elements)

Then when you call the playSong function you can use the sizeof "trick" to get the number of elements (if and only if it is an actual array and not a pointer):

playSong(mySong, sizeof mySong / sizeof mySong[0]);
Sign up to request clarification or add additional context in comments.

1 Comment

you can also define the array length function #define arrayLength( x ) (sizeof (x) / sizeof (x[0])) and then use it as: playSong(mySong, arrayLength(mySong));
1

Twodimensional arrays are only the scond best choice in most cases. I prefer to have a one-dimensional array of dedicated items.

struct Tone {unsigned int freq; byte duration;};
Tone mySong[] {
           {G2, 2}, 
           {B2, 1}, 
           {D3, 1}, 
           {G3, 2}
 };

Of course Joachim's reply about the unknown size, when supplying a Tone song[] parameter, is true as well. Either supply number of elements as an extra parameter, or define a

const Tone EndOfSong {0,0};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.