Почему «0f» не рассматривается как литерал с плавающей точкой в ​​C ++? - PullRequest
14 голосов
/ 18 октября 2010

Почему 0f не рассматривается как литерал с плавающей запятой в C ++?

#include <iostream>

using namespace std;

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

  return 0;
}

Компиляция выше дает мне

C2509 (синтаксическая ошибка: 'плохой суффиксна номер ')

с использованием VS2008.

Ответы [ 6 ]

22 голосов
/ 29 октября 2010

Если бы было явно заявленная причина для этого проектного решения, это было бы в документе «Обоснование» C99 (C ++ дословно скопировал весь этот материал из C, не пересматривая его).Но нет.Это все, что сказано о суффиксе 'f':

§6.4.4.2 Плавающие константы

В соответствии с существующей практикой, константа с плавающей точкой имеет тип double.Поскольку C89 допускает выполнение выражений, которые содержат только float операндов в float арифметике, а не double, метод выражения явный float константы желательны.Тип long double вызывает аналогичные проблемы.

Добавлены суффиксы F и L для передачи информации о типе с помощьюплавающие константы, очень похожие на суффикс L для длинных целых чисел.Тип плавающих констант по умолчанию остается двойным для совместимости с предыдущей практикой.В качестве суффиксов также допускаются строчные буквы f и l.

Там есть подразумеваемая причина, хотя,Обратите внимание на формулировку: «добавлены суффиксы ... для передачи информации о типе с плавающими константами».Авторы стандарта думали, что числовые константы как уже однозначно являются либо целыми числами, либо числами с плавающей запятой к тому времени, как вы получите суффикс.Суффикс только для дополнительной специфики в категории, он не может перевернуть число из одной категории в другую.Это подтверждается фактической грамматикой (C99 §6.4.4), в которой first определяет числовые константы как целочисленные или плавающие, а затем определяет отдельные классы суффиксовза каждый.

20 голосов
/ 19 октября 2010

Предполагая, что грамматика, используемая C ++ для констант с плавающей запятой, такая же, как и для C (что я считаю верным), мы имеем:

Определения некоторых ярлыков, взятых из 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)*

Теперь f или F, которые вы видите в конце чисел с плавающей запятой, определены в FS выше.

Теперь давайте посмотрим, как грамматика распознает действительныеконстанты с плавающей точкой:

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

Теперь, если вы внимательно посмотрите, нет правила, которое бы идентифицировало 0f.

Используя правило 1, мы можем получить 0e0f

ИспользуяПравило2 у нас может быть .0f или 0.0f

Используя правило3, мы можем иметь 0.f или 0.0f

То, что на самом деле происходит в вашем случае, это 0 из 0fбудет использоваться лексическим анализатором как целочисленная константа D, а f будет использоваться как токен FS.Теперь, когда синтаксический анализ видит D, за которым следует FS, для которого нет соответствующего правила, он выдает ошибку:

error: invalid suffix "f" on integer constant
15 голосов
/ 18 октября 2010

Поскольку 0 является целочисленной константой.

edit: Сообщение об ошибке, выданное codepad.org (предположим, g ++), может быть немного проще для понимания.msgstr "ошибка: неверный суффикс" f "на целочисленной константе".«0.f» будет работать, потому что 0. (или 0.0, то же самое) является десятичной константой, и запрос десятичной константы в качестве числа с плавающей точкой имеет больше смысла, чем запрос целочисленной константы в качестве числа с плавающей точкой:)

11 голосов
/ 18 октября 2010

Потому что вам нужно 0.0f.

3 голосов
/ 14 мая 2012

Вот вам «потому что»: если константа int с суффиксом f будет автоматически преобразована в float, то 0x0f будет неоднозначным.

0 голосов
/ 09 июня 2015

Это не обязательно единственная причина, но суффикс l или L может быть применен к целочисленному литералу или литералу с плавающей точкой. 42L относится к типу long int; 42.0L относится к типу long double.

Числовой литерал с суффиксом L должен быть неоднозначным, чтобы определить, является ли оно целым или с плавающей точкой. Разрешение суффикса F само по себе определять тип литерала было бы непоследовательным и потенциально запутанным. Это также затруднило бы добавление новых суффиксов в будущих версиях языка.

...