Jin
Jin

Reputation: 1948

About conversion specifier in C

I have a question about conversion specifier in C.

In the 5th sentence if I use %lf or %Lf instead of %f, no error occurs. But why does error happen if I use %f?

#include <stdio.h>

int main(void)
{
    long double num;
    printf("value: ");
    scanf("%f",&num);  // If I use %lf or %Lf instead of %f, no error occurs. 
    printf("value: %f \n",num);
}

Upvotes: 1

Views: 767

Answers (2)

Daniel Rudy
Daniel Rudy

Reputation: 1439

In looking at the man page for printf(3) on a FreeBSD system (which is POSIX, by the way), I get the following:

The following length modifier is valid for the a, A, e, E, f, F, g, or G conversion:

     Modifier    a, A, e, E, f, F, g, G
     l (ell)     double (ignored, same behavior as without it)
     L           long double

I have used the conversions with a 32-bit float data type. But the issue here is that the reason is because different float formats have different sizes, and the printf function needs to know which one it is so it can properly make that conversion. Using %Lf on a float may cause a segmentation error because the conversion is accessing data outside the variable, so you get undefined behavior.

  • float: 32-bit
  • double: 64-bit
  • long double: 80-bit

Now for the long double, the actual size is defined by the platform and the implementation. 80 bits is 10 bytes, but that doesn't exactly fit within a 32-bit alignment without padding. So most implementations use either 96-bits or 128-bits (12 bytes or 16 bytes respectively) to set the alignment.

Be careful here though, just because it might take 128-bits doesn't mean that it is a __float128 (if using gcc or clang). There is at least one platform where specifying long double does mean a __float128 (SunOS, I think), but it is implemented in software and is slow. Furthermore, some compilers (Microsoft and Intel come to mind) long double = double unless you specify a switch on the command line.

Upvotes: 0

R Sahu
R Sahu

Reputation: 206717

%f is meant to be used for reading floats, not doubles or long doubles.

%lf is meant to be used for reading doubles.

%Lf is meant to be used for reading long doubles.

If your program works with %lf when the variable type is long double, it's only a coincidence. It works probably because sizeof(double) is the same as sizeof(long double) on your platform. In theory, it is undefined behavior.

Upvotes: 6

Related Questions