19

Why isn't 0f treated as a floating point literal in C++?

#include <iostream>

using namespace std;

int main(){
  cout << 0f << endl;

  return 0;
}

Compiling the above gives me

C2509 (syntax error: 'bad suffix on number')

using VS2008.

mskfisher
  • 3,291
  • 4
  • 35
  • 48
Agnel Kurian
  • 57,975
  • 43
  • 146
  • 217
  • 6
    "Why" questions about small arbitrary points in language design generally cannot be answered satisfactorily. – David Thornley Oct 18 '10 at 17:08
  • 2
    @David - Thanks, man. That's very informative. – Agnel Kurian Oct 18 '10 at 17:09
  • 12
    @Vulcan: Unfortunately, that's about as informative as it gets. You're not getting better than Oli Charlesworth's and Dakota Hawkins' answers below, and you're not happy with them. Fundamentally, you're asking about the reasons for a small decision in the C grammar that was made over thirty years ago. It is very likely that there was no explicit reason. – David Thornley Oct 18 '10 at 17:14
  • 1
    Hard to see why this question has 6 down votes. Its a good question which gives an insight of the working of parser and scanner. – codaddict Oct 19 '10 at 06:53
  • 1
    @coaddict: I don't think it should be downvoted, but at the same time, I don't think we've learnt anything interesting about the parser! It's just an arbitrary language specification that doesn't have any impact in practice. – Oliver Charlesworth Oct 20 '10 at 10:07
  • @Oli, I wouldn't be so absolutely sure that it has no impact in practice. – Agnel Kurian Oct 20 '10 at 15:28
  • 1
    @Vulcan: Can you give me a counter-example? – Oliver Charlesworth Oct 20 '10 at 16:00

6 Answers6

24

If there was an explicitly stated reason for this design decision, it would be in the C99 "Rationale" document (C++ copied all this stuff verbatim from C without reconsidering it). But there isn't. This is everything that's said about the 'f' suffix:

§6.4.4.2 Floating constants

Consistent with existing practice, a floating-point constant is defined to have type double. Since C89 allows expressions that contain only float operands to be performed in float arithmetic rather than double, a method of expressing explicit float constants is desirable. The long double type raises similar issues.

The F and L suffixes have been added to convey type information with floating constants, much like the L suffix does for long integers. The default type of floating constants remains double for compatibility with prior practice. Lower-case f and l are also allowed as suffixes.

There is an implied reason, though. Note the wording: "the ... suffixes have been added to convey type information with floating constants." The authors of the standard were thinking of numeric constants as already being unambiguously either integer or floating point by the time you get to the suffix. The suffix is only for extra specificity within the category, it can't flip a number from one category to another. This is backed up by the actual grammar (C99 §6.4.4) which first defines numeric constants as being either integer-constants or floating-constants, and then defines separate classes of suffixes for each.

zwol
  • 135,547
  • 38
  • 252
  • 361
  • 4
    +1. This is the only answer that really provides an inkling of the likely rationale behind this decision. – Brian Oct 29 '10 at 17:31
20

Assuming grammar used by C++ for floating point constants is same as that for C (which I think is true), we have:

Definitions of some shortcuts taken from ANSI C grammar

D      [0-9]
L      [a-zA-Z_]
H      [a-fA-F0-9]
E      [Ee][+-]?{D}+
FS     (f|F|l|L)
IS     (u|U|l|L)*

Now the f or F you see at the end of the floating points is in defined in FS above.

Now lets see the grammar to recognize valid floating point constants:

{D}+{E}{FS}?        
{D}*"."{D}+({E})?{FS}?  
{D}+"."{D}*({E})?{FS}?  

Now if you see carefully there is no rule that would identify 0f.

Using rule1 we can have 0e0f

Using rule2 we can have .0f or 0.0f

Using rule3 we can have 0.f or 0.0f

What actually happen in your case is the 0 of 0f will be consumed by the lexical analyzer as an integer constant D and the f will be consumed as the FS token. Now when the parse sees a D followed by FS for which there is no matching rule, it spits out the error:

error: invalid suffix "f" on integer constant
codaddict
  • 445,704
  • 82
  • 492
  • 529
15

Because the 0 is an integer constant.

edit: The error message given by codepad.org (assume g++) may be a little easier to understand. "error: invalid suffix "f" on integer constant". A "0.f" will work because 0. (or 0.0, same thing) is a decimal constant, and asking for a decimal constant to be a float makes more sense than asking for an integer constant to be a float :)

  • 2
    @Dakota, That's precisely why I added the 'f' suffix in order to force the compiler to treat it as a float. – Agnel Kurian Oct 18 '10 at 17:09
  • f can only be applied to a double literal (such as 0.0), and 0 is an int literal. – Etienne de Martel Oct 18 '10 at 17:12
  • @Etienne, and the question is why? – Agnel Kurian Oct 18 '10 at 17:14
  • Eh, because the standard says so? That's a crappy answer, I know, but I can't think of another reason. – Etienne de Martel Oct 18 '10 at 17:15
  • 1
    Then I suppose your answer is "because that's the way it works". The compiler treats integer constants and decimal constants differently. A 0.0 by itself is going to be a double, so you can add the 'f' to make it a float. A 0 by itself is going to be an integer, and the floating point suffixes wouldn't apply. Similarly, "0.0UL" probably won't compile. – Dakota Hawkins Oct 18 '10 at 17:16
  • 11
    @Vulcan Eager: Does it really matter why? it matters in as much as asking why to index an array you use [] and not <> or why the entry point for your program is a function called `main` and not `StartHere`. There is no why beyond *'cos the standard says so* – David Rodríguez - dribeas Oct 18 '10 at 17:18
11

Because you need 0.0f.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
3

Here's a 'because' for you: if an int constant with an f suffix was automatically converted to float, then 0x0f would be ambiguous.

TonyK
  • 16,761
  • 4
  • 37
  • 72
  • 1
    Not necessarily; the `0x` suffix, in the absence of a `p+EXP` or `p-EXP` suffix, is already treated as forcing integerness (i.e. `0x0.0` is a syntax error); there's no ambiguity with `0x0.0p+0f` because the exponent is decimal even though the mantissa is hex. However, this is still an excellent point which may well have been in the minds of the committee members. – zwol Sep 11 '12 at 23:48
0

This isn't necessarily the only reason, but an l or L suffix can be applied to an integer literal or to a floating-point literal. 42L is of type long int; 42.0L is of type long double.

A numeric literal with an L suffix must be disambiguated to determine whether it's integer or floating-point. Allowing an F suffix by itself to determine the type of a literal would be inconsistent and potentially confusing. It would also make it more difficult to add new suffixes in future versions of the language.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631