Reputation: 1948
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
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
, orG
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.
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
Reputation: 206717
%f
is meant to be used for reading float
s, not double
s or long double
s.
%lf
is meant to be used for reading double
s.
%Lf
is meant to be used for reading long double
s.
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