Search code examples
carduinochardoubleavr

Confused about dtostrf function


I am currently working on a personal AVR project and wrote a function for transmitting a double to my serial LCD screen using UART. For this, I convert a double into a char array and then transmit it char by char, serially.

What confuses me is what the length of the char buffer array has to be. The length of the array does not seem to correspond to the size of a double. Funnily enough, I can set the the length of the array to 0, and it will still work, like this:

    void USART_Transmit_Double(double doubleNumber) {

    char aNumberAsString[0];
    dtostrf(doubleNumber, 3, 0, aNumberAsString);

    USART_Transmit_String(aNumberAsString);
}

Here I am printing number 1234 in the main loop and it appears on my LCD just fine. If I change the precision to 1 however, the entire thing goes haywire.

I tested the same function on my Arduino and keep getting completely different results, on it each character seems to correspond to each element of the array, so if I wanted to print 1234.2, I would have to set the buffer length to 6.

So what's going on here?


Solution

  • You are running into undefined behavior. In particular, in this link, the phrase: Examples of undefined behavior are memory accesses outside of array bounds,... would likely apply to your described scenario. It may work a thousand times if the memory you are attempting to access (but do not own) does not happen to violate another variable's memory space. The first time it does, your program will crash.

    The following statement, although legal, creates a useless variable, and is likely the reason you are seeing odd results:

    char aNumberAsString[0];
    

    Addressing your comment:
    You may be confusing the index value necessary to create a buffer containing a single value, with the index value necessary to access that value once the variable is created. i.e.

    char aNumberAsString[1] = 'A'; //creates an array of 1 char ([1])
    

    will create a variable that can contain a single char value.

    char value = aNumberAsString[0]; // accesses the only value in array ([0])
    

    EXAMPLE:
    See an example of how to use the dtostrf function here.
    Note the size of the variables this example is using:

    static float f_val = 123.6794;
    static char outstr[15];
    

    to support the following call:

     dtostrf(f_val,7, 3, outstr);
    

    Which produces the following output:

    123.679