[c] Using floats with sprintf() in embedded C

Guys, I want to know if float variables can be used in sprintf() function.

Like, if we write:

sprintf(str,"adc_read = %d \n",adc_read);

where adc_read is an integer variable, it will store the string

"adc_read = 1023 \n"

in str (assuming that adc_read = 1023)

How can I use a float variable in place of integer?

This question is related to c embedded floating-point printf

The answer is


Isn't something like this really easier:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char str[10];
float adc_read = 678.0123;

dtostrf( adc_read, 3, 4, temp );
sprintf(str,"adc_read = %10s \n", temp);
printf(temp);

Yes you can. However, it depends on the C-library that you are linking against and you need to be aware of the consequences.

Since you are programming for embedded applications, realise that floating-point support is emulated for a lot of embedded architectures. Compiling in this floating-point support will end up increasing the size of your executable significantly.


use the %f modifier:

sprintf (str, "adc_read = %f\n", adc_read);

For instance:

#include <stdio.h>

int main (void) 
{
    float x = 2.5;
    char y[200];

    sprintf(y, "x = %f\n", x);
    printf(y);
    return 0;
}

Yields this:

x = 2.500000


%g can do this:

#include <stdio.h>
int main() {
  float w = 234.567;
  char x[__SIZEOF_FLOAT__];
  sprintf(x, "%g", w);
  puts(x);
}

Yes, and no. Despite what some other replies have said, the C compiler is required to perform conversions for sprintf(), and all other variadic functions, as follows:

  • char => int
  • short => int
  • float => double

(and signed/unsigned variants of the above integral types)

It does this precisely because sprintf() (and the other print()-family functions) would be unusable without it. (Of course, they're pretty unusable as it is.)

But you cannot assume any other conversions, and your code will have undefined behaviour - read: crash! - if you do it.


Look in the documentation for sprintf for your platform. Its usually %f or %e. The only place you will find a definite answer is the documentation... if its undocumented all you can do then is contact the supplier.

What platform is it? Someone might already know where the docs are... :)


Many embedded systems have a limited snprintf function that doesn't handle floats. I wrote this, and it does the trick fairly efficiently. I chose to use 64-bit unsigned integers to be able to handle large floats, so feel free to reduce them down to 16-bit or whatever needs you may have with limited resources.

#include <stdio.h>   // for uint64_t support.


int  snprintf_fp( char destination[], size_t available_chars, int decimal_digits,
                  char tail[], float source_number )
{
    int   chars_used  = 0;    // This will be returned.


    if ( available_chars > 0 )
    {
        // Handle a negative sign.
        if ( source_number < 0 )
        {
            // Make it positive
            source_number = 0 - source_number;
            destination[ 0 ] = '-';
            ++chars_used;
        }

        // Handle rounding
        uint64_t zeros = 1;
        for ( int i = decimal_digits; i > 0; --i )
            zeros *= 10;

        uint64_t source_num = (uint64_t)( ( source_number * (float)zeros ) + 0.5f );

        // Determine sliding divider max position.
        uint64_t  div_amount = zeros;       // Give it a head start
        while ( ( div_amount * 10 ) <= source_num )
            div_amount *= 10;

        // Process the digits
        while ( div_amount > 0 )
        {
            uint64_t whole_number = source_num / div_amount;
            if ( chars_used < (int)available_chars )
            {
                destination[ chars_used ] = '0' + (char)whole_number;
                ++chars_used;

                if ( ( div_amount == zeros ) && ( zeros > 1 ) )
                {
                    destination[ chars_used ] = '.';
                    ++chars_used;
                }
            }
            source_num -= ( whole_number * div_amount );
            div_amount /= 10;
        }


        // Store the zero.
        destination[ chars_used ] = 0;

        // See if a tail was specified.
        size_t tail_len = strlen( tail );

        if ( ( tail_len > 0 ) && ( tail_len + chars_used < available_chars ) )
        {
            for ( size_t i = 0; i <= tail_len; ++i )
                destination[ chars_used + i ] = tail[ i ];
            chars_used += tail_len;
        }
    }

    return chars_used;
}

main()
{
    #define TEMP_BUFFER_SIZE 30
    char temp_buffer[ TEMP_BUFFER_SIZE ];
    char  degrees_c[] = { (char)248, 'C', 0 };
    float  float_temperature = 26.845f;

    int len = snprintf_fp( temp_buffer, TEMP_BUFFER_SIZE, 2, degrees_c, float_temperature );
}

Don't expect sprintf (or any other function with varargs) to automatically cast anything. The compiler doesn't try to read the format string and do the cast for you; at runtime, sprintf has no meta-information available to determine what is on the stack; it just pops bytes and interprets them as given by the format string. sprintf(myvar, "%0", 0); immediately segfaults.

So: The format strings and the other arguments must match!


Similar to paxdiablo above. This code, inserted in a wider app, works fine with STM32 NUCLEO-F446RE.

#include <stdio.h>
#include <math.h>
#include <string.h>
void IntegFract(char *pcIntegStr, char *pcFractStr, double dbValue, int iPrecis);

main()
{
   char acIntegStr[9], acFractStr[9], char counter_buff[30];
   double seconds_passed = 123.0567;
   IntegFract(acIntegStr, acFractStr, seconds_passed, 3);
   sprintf(counter_buff, "Time: %s.%s Sec", acIntegStr, acFractStr);
}

void IntegFract(char *pcIntegStr, char *pcFractStr, double dbValue, int 
iPrecis)
{
    int iIntegValue = dbValue;
    int iFractValue = (dbValue - iIntegValue) * pow(10, iPrecis);
    itoa(iIntegValue, pcIntegStr, 10);
    itoa(iFractValue, pcFractStr, 10);
    size_t length = strlen(pcFractStr);
    char acTemp[9] = "";
    while (length < iPrecis)
    {
        strcat(acTemp, "0");
        length++;
    }
    strcat(acTemp, pcFractStr);
    strcpy(pcFractStr, acTemp);
}

counter_buff would contain 123.056 .


Don't do this; integers in C/C++ are always rounded down so there is no need to use the floor function.

char str[100]; 
int d1 = value;

Better to use

int d1 = (int)(floor(value));

Then you won't get rounding up of the integer part (68.9999999999999999 becomes 69.00..). 68.09999847 instead of 68.1 is difficult to avoid - any floating point format has limited precision.


Yes of course, there is nothing special with floats. You can use the format strings as you use in printf() for floats and anyother datatypes.

EDIT I tried this sample code:

float x = 0.61;
char buf[10];
sprintf(buf, "Test=%.2f", x);
printf(buf);

Output was : Test=0.61


Yes, use %f


Examples related to c

conflicting types for 'outchar' Can't compile C program on a Mac after upgrade to Mojave Program to find largest and second largest number in array Prime numbers between 1 to 100 in C Programming Language In c, in bool, true == 1 and false == 0? How I can print to stderr in C? Visual Studio Code includePath "error: assignment to expression with array type error" when I assign a struct field (C) Compiling an application for use in highly radioactive environments How can you print multiple variables inside a string using printf?

Examples related to embedded

Compiling an application for use in highly radioactive environments Sorting 1 million 8-decimal-digit numbers with 1 MB of RAM What does this GCC error "... relocation truncated to fit..." mean? How do you implement a class in C? Understanding Linux /proc/id/maps Using floats with sprintf() in embedded C What is the difference between C and embedded C? Unit Testing C Code

Examples related to floating-point

Convert list or numpy array of single element to float in python Convert float to string with precision & number of decimal digits specified? Float and double datatype in Java C convert floating point to int Convert String to Float in Swift How do I change data-type of pandas data frame to string with a defined format? How to check if a float value is a whole number Convert floats to ints in Pandas? Converting Float to Dollars and Cents Format / Suppress Scientific Notation from Python Pandas Aggregation Results

Examples related to printf

How I can print to stderr in C? How can you print multiple variables inside a string using printf? Unsigned values in C How to print multiple variable lines in Java Scanf/Printf double variable C Format specifier %02x %i or %d to print integer in C using printf()? What is the printf format specifier for bool? printf() prints whole array Printf width specifier to maintain precision of floating-point value