Содержание
Я использую Visual C ++ 2012 и компилирую из командной строки следующие файлы:
Связывание с MSVCRT.LIB, а не LIBCMT, чтобы избежать ошибки времени выполнения R6002.
Значение, которое выводится, составляет 0,00000 для этой программы.
Однако, если я выполняю ту же самую вещь в C ++
Теперь он печатает 6, как и должно быть.
Какая разница? Это связано с самими языками (C vs C ++) или методами вывода (cout vs printf), или это просто причуды с MSVC?
Решение
Выражение 18/4+18%4 оценивает int , и вы запрашиваете поплавок. Вы должны всегда компилировать с включенными предупреждениями и обращать на них внимание (говорят предупреждение — ошибка, ожидающая, и они правы).
Это то, что говорит мне мой компилятор (GCC 4.8.1) (и даже без принуждения -Wall ):
С другой стороны, std::cout Операция может определить тип вашего выражения и правильно транслировать его на экран.
Другие решения
Функция C передается целое число, но вы говорите это (с %f ) ожидать числа с плавающей запятой двойной точности, поэтому оно не выполняется. Функция C ++ знает, что ей передается целое число, поэтому она работает правильно.
в С пример этого выражения 18/4+18%4 будет оценивать ИНТ так как все операнды целочисленные константы но вы указываете, что это двойной в printf и поэтому он будет обработан неправильно. С другой стороны, если бы вы использовали Плавающая постоянная в части деления выражения, например, 18.0/4+18%4 все выражение оценило бы к двойной. В качестве альтернативы вы могли бы использовать "%d" в спецификаторе формата.
Это тоже неопределенное поведение неправильно указать формат printf и это также демонстрирует, почему важно строить с предупреждениями, используя gcc -Wall Я получаю следующее предупреждение (видеть это жить ):
В C ++ станд :: соиЬ «s оператор имеет перегрузку для int и поэтому это будет называться в этом случае. Мы можем видеть эту перегрузку, многие другие требуются Проект стандарта C ++ , в разделе 27.7.3.1 Шаблон класса basic_ostream мы находим следующее объявление оператора:
Для полноты, возвращаясь к неопределенному поведению, Проект стандарта C99 в разделе 7.19.6.1 Функция fprintf который printf секция ссылается на формат строки абзаца 9 говорит:
Если спецификация преобразования недопустима, поведение не определено. […]
Но Printf строка формата «% .5f» ожидает двойной.
С помощью c ++ и ostreams язык может автоматически определять тип вывода.
Просто измените свой C-код следующим образом:
Другие правильно указали на несоответствие int / double в вашем выражении printf (). Я просто хочу прокомментировать ваше утверждение: «Связывание с MSVCRT.LIB, а не с LIBCMT, чтобы избежать ошибки времени выполнения R6002». Такая простая программа не должна чрезмерно обременять среду выполнения, поэтому такая ошибка во время выполнения должна быть красным флагом неопределенного поведения в вашем коде.
Быстрый Google «MSVCRT R6002» говорит:
C Run-Time Ошибка R6002
поддержка плавающей запятой не загружена
Необходимая библиотека с плавающей точкой не была связана.
Исправить, проверив следующие возможные причины
- Программа была скомпилирована или связана с опцией, такой как / FPi87, для которой требуется сопроцессор, но программа была запущена на машине, на которой не был установлен сопроцессор.
- Строка формата для функции printf_s или scanf_s содержала спецификацию формата с плавающей запятой, а программа не содержала значений или переменных с плавающей запятой.
- Компилятор минимизирует размер программы, загружая поддержку с плавающей точкой только при необходимости. Компилятор не может определить спецификации формата с плавающей точкой в строках формата, поэтому он не загружает необходимые подпрограммы с плавающей точкой.
- Используйте аргумент с плавающей точкой, чтобы соответствовать спецификации формата с плавающей точкой, или выполните присвоение с плавающей точкой в другом месте программы. Это приводит к загрузке поддержки с плавающей точкой.
- В программе на разных языках библиотека C была указана перед библиотекой FORTRAN, когда программа была связана. Перепроверьте и укажите библиотеку C в последнюю очередь.
Урок здесь, конечно, заключается в том, что вы должны внимательно следить за предупреждениями компилятора и среды выполнения & ошибки. Если есть сомнения, всегда предполагайте, что проблема в вашем коде, а не в компиляторе.
В C потому что вы явно указываете плавающую точку («% f») в вашем спецификаторе формата printf, поэтому он ожидает аргумент с плавающей точкой. Но вы даете этому аргумент «int», отсюда и проблема.
В зависимости от того, что вы пытаетесь сделать, вы можете:
1) Кастинг (иначе целое числоВыражение плавать
2) Использование setprecision в потоке cout, так же, как вы использовали бы «% .5f» в C:
3) Если вы хочу целое число, использовать printf ("%d", 18/4+18%4);
Если вы хотите такое же поведение (и ответ), вам лучше написать код
чтобы получить int вместо ответа с плавающей точкой. Вы получите тот же результат, что и выбран оператор
В противном случае вы можете использовать явно
получить 6.00000 результат.
Пусть одно из ваших чисел будет значением с плавающей запятой:
Я использую Visual С++ 2012 и компилирую из командной строки следующие файлы:
Связывание с MSVCRT.LIB, а не LIBCMT, чтобы избежать ошибки времени выполнения R6002.
Выводимое значение составляет 0,00000 для этой программы.
Однако, если я выполняю то же самое в С++
Теперь он выдает 6, как и должно.
Какая разница? Это касается самих языков (C vs С++) или методов вывода (cout vs printf), или это просто причуда с MSVC?
c++ c floating-point printf cout
9 ответов
64 Решение Escualo [2013-09-30 23:06:00]
Выражение 18/4+18%4 оценивается как int , и вы запрашиваете float. Вы всегда должны компилировать с включенными предупреждениями и обращать на них внимание (они говорят, что предупреждение — это ошибка, ожидающая появления, и они правы).
Вот что говорит мой компилятор (GCC 4.8.1) (и даже без применения -Wall ):
С другой стороны, операция std::cout позволяет выводить тип вашего выражения и корректно передавать его на экран.
37 Gabe [2013-09-30 23:05:00]
Функция C передает целое число, но вы говорите ему (с %f ), чтобы ожидать число с плавающей запятой с двойной точностью, поэтому он терпит неудачу. Функция С++ знает, что ей передается целое число, поэтому оно работает правильно.
В примере C это выражение 18/4+18%4 будет вычисляться как int, так как все операнды являются целыми константами, но вы указываете, что это двойное значение printf , и поэтому оно будет обрабатываться некорректно. С другой стороны, если бы вы использовали плавучую константу в части деления выражения, например 18.0/4+18%4 , все выражение оценивалось бы двойным. В качестве альтернативы вы могли бы использовать "%d" в спецификаторе формата.
Это также undefined поведение, чтобы неправильно указать формат printf , и это также демонстрирует важность построения с предупреждениями, используя gcc -Wall Я получаю следующее предупреждение (см. live):
Для полноты, обращаясь к поведению undefined, черновик проекта C99 в разделе 7.19.6.1 Функция fprintf, которая printf ссылается на строку форматирования в абзаце 9:
Если спецификация преобразования недействительна, поведение undefined. [. ]
оценивает значение int.
Но строка формата printf "%.5f" ожидает двойной.
С С++ и ostream, язык может автоматически определять тип вывода.
Просто измените свой C-код на следующий:
8 Drew Hall [2013-10-01 14:03:00]
Другие правильно указали совпадение int/double в вашем заявлении printf(). Я просто хочу прокомментировать ваше выражение: "Связывание с MSVCRT.LIB, а не LIBCMT, чтобы избежать ошибки R6002 во время выполнения". Программа, такая простая, не должна излишне налагать налоговую нагрузку на среду выполнения, поэтому такая ошибка должна быть красным значком поведения undefined в вашем коде.
Быстрый Google "MSVCRT R6002" говорит:
C Ошибка времени выполнения R6002поддержка с плавающей запятой не загружена
Необходимая библиотека с плавающей запятой не была связана. Исправить, выполнив следующие возможные причины:
- Программа была скомпилирована или связана с опцией, например /FPi 87, для которой требуется сопроцессор, но программа была запущена на машине, на которой не было установлен сопроцессор.
- Строка формата для функции printf_s или scanf_s содержала спецификацию формата с плавающей запятой, и программа не содержала никаких значений или переменных с плавающей запятой.
- Компилятор минимизирует размер программы, загружая поддержку с плавающей запятой только тогда, когда это необходимо. Компилятор не может определить спецификации формата с плавающей запятой в строках формата, поэтому он не загружает необходимые процедуры с плавающей запятой.
- Используйте аргумент с плавающей запятой, чтобы соответствовать спецификации формата с плавающей запятой, или выполнить назначение с плавающей запятой в другом месте программы. Это приводит к загрузке поддержки с плавающей запятой.
- В программе на смешанном языке библиотека C была указана перед библиотекой FORTRAN при подключении программы. Переименуйте и укажите последнюю библиотеку C.
Урок здесь, конечно же, заключается в том, что вы должны уделять пристальное внимание предупреждениям и ошибкам компилятора и времени выполнения. Когда вы сомневаетесь, всегда предполагайте, что проблема заключается в вашем коде, а не в компиляторе.
4 paulsm4 [2013-09-30 23:05:00]
В C, потому что вы явно указываете с плавающей точкой ( "% f" ) в спецификаторе формата printf, поэтому он ожидает аргумент с плавающей запятой. Но вы даете ему аргумент "int", следовательно, проблема.
В зависимости от того, что вы пытаетесь сделать, вы можете:
1) Выделение выражения (в противном случае целого) для float
2) Используя setprecision в вашем потоке cout, так же, как вы используете "%.5f" в C:
3) Если вы хотите целое число, используйте printf ("%d", 18/4+18%4);
Если вам нужно одинаковое поведение (и ответ), вам лучше закодировать
чтобы получить ответ int вместо числа с плавающей точкой. Вы получите тот же результат, что и оператор , выбранный
В противном случае вы можете явно использовать
чтобы получить результат 6.00000 .
1 smac89 [2013-09-30 23:16:00]
Пусть одно из ваших чисел будет значением с плавающей запятой:
Одна из возможных альтернатив — типизация литералов (или самого выражения):
Я использую Visual C++ 2012 и компилирую из командной строки следующие файлы:
связывание с MSVCRT.LIB, а не LIBCMT, чтобы избежать ошибки выполнения R6002.
Выходное значение для этой программы равно 0.00000.
однако, если я выполняю то же самое в C++
теперь он печатает 6, как и должно.
в чем разница? Это связано с самими языками (C vs C++) или с выходом методы (cout vs printf), или это просто причуда с MSVC?
9 ответов
выражение 18/4+18%4 оценивает в int , и вы запрашиваете поплавок. Вы всегда должны компилировать с включенными предупреждениями и обращать на них внимание (они говорят предупреждение-это ошибка ждет, и они правы).
это то, что мой компилятор (GCC 4.8.1) говорит мне (и даже без принуждения -Wall ):
С другой стороны, std::cout операция способна вывести тип вашего выражения и правильно передать его в ваш экран.
функция C передается целым числом, но вы говорите это (с %f ) ожидать числа с плавающей запятой двойной точности, поэтому он терпит неудачу. Функция C++ знает, что ей передается целое число, поэтому она работает правильно.
на C пример этого выражения 18/4+18%4 оценивают в int так как все операнды целочисленные константы но вы указываете, что это двойной to printf и поэтому он будет обработан неправильно. С другой стороны, если вы используете плавающие константы в части деления выражения, например 18.0/4+18%4 все выражение было бы оценено в a двойной. В качестве альтернативы вы могли бы использовать "%d" в спецификаторе формата.
это тоже неопределенное поведение неправильно указать формат в printf и это также демонстрирует, почему важно строить с предупреждениями, используя gcc -Wall Я получаю следующее предупреждение(видеть live):
для полноты, возвращаясь к неопределенному поведению,проект стандарта C99 в разделе 7.19.6.1 функция fprintf, который printf ‘ы раздел ссылается на строку формата paragraph 9 говорит:
если спецификация преобразования является недопустимым, поведение неопределено.[. ]
оценивает в int.
но printf формат строки "%.5Ф" ожидает двойная.
С помощью c++ и ostreams язык может автоматически определять тип вывода.
просто измените свой C-код на следующий:
Другие правильно указали на несоответствие int/double в вашем операторе printf (). Я просто хочу прокомментировать ваше заявление", — говорится в сообщении MSVCRT.LIB, а не LIBCMT, чтобы избежать ошибки выполнения R6002."Такая простая программа не должна чрезмерно облагать налогом среду выполнения, поэтому такая ошибка выполнения должна быть красным флагом неопределенного поведения в вашем коде.
быстрый Google "MSVCRT R6002" говорит:
C Ошибка Времени Выполнения R6002 поддержка с плавающей запятой не загружена
необходимая библиотека с плавающей запятой не была связана. Исправить, проверив следующие возможные причины
- программа была скомпилирована или связана с опцией, такой как /FPi87, для которой требуется сопроцессор, но программа была запущена на машине, на которой не был установлен сопроцессор.
- строка формата для функции printf_s или scanf_s содержит формат с плавающей запятой спецификация и программа не содержали никаких значений или переменных с плавающей запятой.
- компилятор минимизирует размер программы, загружая поддержку с плавающей запятой только при необходимости. Компилятор не может обнаружить спецификации формата с плавающей запятой в строках формата, поэтому он не загружает необходимые процедуры с плавающей запятой.
- используйте аргумент с плавающей запятой для соответствия спецификации формата с плавающей запятой или выполните назначение с плавающей запятой в другом месте программы. Это приводит к загрузке поддержки с плавающей запятой.
- в программе на смешанном языке библиотека C была указана перед библиотекой FORTRAN, когда программа была связана. Повторно свяжите и укажите библиотеку C последней.
урок здесь, конечно, заключается в том, что вы должны уделять пристальное внимание предупреждениям компилятора и времени выполнения и ошибкам. Когда вы сомневаетесь, всегда предполагайте, что проблема в вашем коде, а не в компилятор.
В C, поскольку вы явно указываете плавающую точку ("%f") в описателе формата printf, поэтому он ожидает аргумент с плавающей точкой. Но вы даете ему аргумент "int", следовательно, проблема.
в зависимости от того, что вы пытаетесь сделать, вы можете:
1) литье (в противном случае целое) выражение для float
2) с помощью setprecision в поток cout, так же, как вы бы использовать "%.5Ф" в C:
3) Если вы хочу целое число, используйте printf ("%d", 18/4+18%4);
если вы хотите такое же поведение (и ответ) вы бы лучше код
чтобы получить ответ int Вместо ответа с плавающей запятой. Вы получите тот же результат, что и выбранный оператор
в противном случае, вы можете использовать явно
и 6.00000 результат.
пусть одно из ваших чисел будет значением с плавающей запятой:
одной из возможных альтернатив является типизация литералов (или самого выражения):