I had troubles getting two things working, until I rewrote the code.
1. sizeof() an array
I have declared an array like this:
uint16_t main_theme[] = {
B4, AISS4, A4, GISS4, G4, C5, B4, AISS4, END
};
Those macros are just uint16_t numbers everyone (frequencies to be played). Later I play those tones with this:
void play_melody(uint16_t *mel)
{
for (uint16_t *p = mel; *p != END; p++)
{
if (*p != Z)
carrier.Buzzer.sound(*p);
delay(TONEDELAY);
carrier.Buzzer.noSound();
delay(TONEOFFTIME);
}
}
That works quite well. TONEDELAY is a value of 70 and TONEOFFTIME is 3. In my code I call the function like this:
if (soundOn)
play_melody(main_theme);
else
delay((TONEDELAY + TONEOFFTIME) * (sizeof(main_theme) - 2) / 2);
Everything works like a charm when I have the sound on. But when the sound is off and the delay is supposed to happen, which should last as long as the melody, the delay is not calculated. Each element except the terminating END in the array is a tone that lasts 70 milliseconds (TONEDELAY), after that there's a 3 millisecond silence (TONEOFFTIME). I expect sizeof() to give the total number of bytes in the array. (I take 2 off for the terminating array element, then divide by two to get the number of uint16_t elements).
The strange thing is that declaring the array with uint16_t main_theme[] = {
will make sizeof() go lost. It couldn't see the size of the array, it sounded like it just gave me the size of one uint16_t. I changed the code to uint16_t main_theme[9] = {
and now it worked. To check whether I found the solution I changed back to uint16_t main_theme[ ] = {
. It still worked! It didn't go back to treating the array as if it had only one element. I repeated the thing with another array. Same happened! uint16_t new_ball_melody[ ] = {
didn't work. Changing to uint16_t new_ball_melody[13] = {
made it work. Changing back to uint16_t new_ball_melody[ ] = {
still working!
My theory is that the compiler doesn't do its job. First, when it sees sizeof(new_ball_melody)
, it fails to count the number of elements in the following ={} thing. It just goes with the datatype. Then when I add the array size, it does its job. It doesn't have to check the {} listing, it just relys on what's in [ ]. And when I change back to [ ] without telling the number of elements, the compiler does a peculiar choice to neglect the empty [ ], probably because now there's no info about a changed array size, so it goes with the size from the previous compilation.
2. char *name = "JOHAN"
I declare a string like char *name = "JOHAN". Then I have a function which should alter the string:
void alter(char *strng)
{
... // stuff like strng[1] = 'G';
}
Everything compiles. But program gets freezed. Somehow I doubted the memory handling here. So I changed it to:
char *name;
name = new char[8];
strcpy(name, "JOHAN");
And now it worked! What happened here? Did I come across two things, where the Arduino compiler doesn't obey the rules of C?