0
\$\begingroup\$

Observe the following example code (Microcontroller used: ATtiny84A):

void toggle_output(unsigned char *string)
{
    for (unsigned char i = 0; i < sizeof(string) - 3; i++)
    {
        PORTB ^= (1 << PORTB0);
    }
} 

toggle_output("test");

I would expect the pin, which is attached to port B0, to toggle 4 times - once for each character in "test"; however, what is happening is that I am ending up with an endless loop. The pin is endlessly toggling when it should only toggle 4 times.

I know that the pin is functioning normally, as I am able to set the output statically high or statically low. And I know that If I give the for loop a fixed number of times to loop, it will do so the expected amount of times. For example:

void toggle_output(unsigned char *string)
{
    for (unsigned char i = 0; i < 5; i++)
    {
        PORTB ^= (1 << PORTB0);
    }
} 

toggle_output();

The above code will cause the pin to toggle 5 times as expected. So for some reason the sizeof operator is yielding some enormous number, or the microcontroller is, for some reason, adding to it. What is even stranger, is if I write an equivalent C program on my computer that just prints a number for each character in a string, it does so as expected:

void number_for_character (unsigned char *string)
{
    for (i = 0; i < sizeof(string) - 3; i++)
    {
        printf("1");
    }
}
number_for_character("test");
OUTPUT: 1111

What is going on here? Why isn't the sizeof operator working with the ATtiny84A?

\$\endgroup\$
7
  • \$\begingroup\$ Inside the function, string is a pointer. A pointer is most likely to have the size of an integer and not the number of characters in the array pointed-to by the pointer. How are you running / debugging this ? on actual hardware or in a simulator ? Perhaps this function is itself being called endlessly and each time it loops only a limited number of times. \$\endgroup\$ – AJN May 5 at 2:51
  • \$\begingroup\$ Use i < strlen(string) if the library provides strlen to do what I think you want it to do. Better yet, store the result of strlen in a variable instead of calling it once in every loop iteration. \$\endgroup\$ – AJN May 5 at 2:53
  • 7
    \$\begingroup\$ Size and length are different notions. \$\endgroup\$ – Paul Ghobril May 5 at 3:11
  • 1
    \$\begingroup\$ sizeof(string) returns the number of bytes that the variable type of string uses for storage. Since string is a pointer, it returns 4 on your 32 bit computer architecture. The input doesn't actually matter. string could even be null. Try changing "test" to "test1234". You will get the exact same output on your computer. \$\endgroup\$ – mkeith May 5 at 5:17
  • 5
    \$\begingroup\$ I’m voting to close this question because it's a pure beginner-level C programming question and has nothing to do with microcontrollers specifically. Should be asked on stackoverflow.com instead (where it will be closed as a duplicate since it's a FAQ). \$\endgroup\$ – Lundin May 5 at 7:34
9
\$\begingroup\$

Don't use the sizeof operator. char[10], char[40], char* are all slightly different data types and return different sizes.

Use strlen to find the length of a string if your micro controller library provides it. If it doesn't, write one yourself by counting till you find the string terminating character, usually '\0'.

See a sample code below.

int i;

// store length in a variable.
// dont call strlen ever loop iteration.
int len = strlen(string);

for(i=0; i< len; i++){
// do something
}
\$\endgroup\$
1
  • 3
    \$\begingroup\$ Don't forget to #include<string.h> \$\endgroup\$ – mkeith May 5 at 5:12
5
\$\begingroup\$

The code works as written, it just makes no sense.

The code uses sizeof to take the size of a pointer to a string and pointers on AVR are 2 bytes long. Subtract three and that's -1, and your loop variable I must be unsigned as -1 is largest positive number that fits to variable i.

What you really want is to take the length of the string given as a parameter and you use strlen for that, not sizeof.

\$\endgroup\$

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