Классический язык программирования Си.
Есть, допустим, такая операция присваивания:
f=1+3*4/6;
В арифметическом выражении нет переменных.
Результат арифметического выражения рассчитывается в ходе выполнения кода, или же компилятор рассчитывает его на стадии компиляции и в код помещает f=3 ?
(1) О, пятничный вопрос =)
В ходе компиляции получится f=3
Как нам говорили в университете на первых курсах: "в военное время синус может равняться 2".
(1) Компилятор ничего не расчитывает - а переводит программу на машинные команды (например, в exe файл) - и потом уже когда запускаете этот exe файл он выполняется на процессоре. А вот транслятор уже выполняет саму программу без перевода в машинные команды - правда, предварительно для оптимизации транслятор переводит программу в байт - код - но это тоже не машинные команды, а просто более удобное для транслятора представление. Также применяется перевод в обратную польскую запись.
(10) какой транслятор для скомпилированной программы на языке си (именно чистый си указан в заголовке) транслирует и куда?
Про оптимизирующую компиляцию упоминать не стоит?
Если в выражении переменной происходит статический расчет, то оптимизатор ее сразу же вычислит и подставит результат. Тоже самое и с конкатенацией строк.
Допускаю, что существуют компиляторы без оптимизаций, или ее возможно отключить. Но в большинстве случае именно так и происходит.
(11) Вы о чем? при чем тут то, что Вы написали. Я писал о том, что транслятор может и не вычислить выражение, а компилятор вычислит сразу же и подставит 3 - т.к. в выражении нет ссылок на переменные - одни числа.
Я писал о том, что транслятор может и не вычислить выражение, а компилятор вычислит сразу же и подставит 3 - т.к. в выражении нет ссылок на переменные - одни числа.
Компилятор ничего не расчитывает - а переводит программу на машинные команды (например, в exe файл) - и потом уже когда запускаете этот exe файл он выполняется на процессоре.
(1) есть более интересная особенность таких вычислений.
Вот, пример:
float x = 4/6;
int f = 1+3*x;
Чему будет равен f ?
Даже если взять полностью предложенный пример в (1), то он будет работать ожидаемо только из-за пограничного условия: целочисленное деление. Усложним:
int f = 1+4/6*3;
(17)В обоих примерах будет зависит от типа компиляции 32 или 64 разрядная, в любом случае будет усечение результата, в первом примера 2 усечения, double в float и double в int, во втором одно double в int
(18) в том то и дело, что пример выше не будет так выполнен. 4/6 это тип int поделенный на тип int. Результат такого деления будет тип int. Итого имеем, что 4/6 будет равен 0.
Даже float x = 4/6 будет равен 0. Автоприведение типов применяется уже к результату вычисления.
Следовательно в обоих случаях f = 1. Неожиданный результат в итоге.
Чтобы результат вычисления был ожидаемым, необходимо осуществить явное приведение:
int f = 1+((double)4/6)*3;
или указать, что один из операндов тип float(к примеру):
int f = 1+4f/6*3
(19) По умолчанию компилятор к числовым константам применят тип double, а результат приводит к типу переменной, то есть будет усечение результата double до float, а усечение double до int приведет к усечение до разрядности которая определена для текущей платформы компиляции. В обоих случаях результаты непредсказуемые, в вашем новом примере вы даете явное указание компилятору какие типы использовать при вычислении.
(20) компилятор тут не причем. В языке си есть стандарт: При делении значение целого типа на значение целого типа результат тоже получается целого типа. Компилятор не может применять к константе целого числа тип double.
(21)компилятор приводит к одному типу оба операнда к максимальному по разрядности типу, выражения int f = 1+((double)4/6)*3; и int f = 1+4f/6*3, разные и могут дать разные результаты и соответственно приведение к int то же не предсказуемое. Все 4 примера, результат не предсказуемый, предсказуемый только в том случае когда в результате вычисления результат будет меньше наибольшего числа в типе int.
(24) по правилам самого языка целые константы имеют тип int. Вот его размер может меняться. Но никак не тип double. Вещественные константы имеют отличную от целых типов написание.
Вывод типа от размера целочисленной константы не рассматриваем. Он может и в long его определить. В рассматриваемом примере тип точно int.
(25) Константы имеют отличное написание, но если записать выражение float i = 4/6 и int i = 4/6 результаты разные, а вычислит он их как double в обоих случаях. Так что выражение 4/6 может иметь и как целое значение и как вещественное.
(26) результат в самой переменной будет разный. Просто разные типы. Вычисление выражения в обоих случаях будет одним и тем же. Целочисленной константой типа int равной 0.
Уже для float i тип int будет неявно приведен к типу float.
(29)вы заблуждаетесь, я перед этим писал что компилятор приводит к максимальному типу все операнды, по сути такие записи выглядят так:
float i = (float)4/6
int i = (int)4/6
само вычисление зависит от компилятора, какой он алгоритм выберет, в 1 и 2 случае, или так:
float i = (float)(double)4/6
int i = (int)(double)4/6
(36) так он и приводит к типу получателя, но уже вычисленный результат. Или он прямо все операнды приводил к типу получателя? Это не может быть.
Вот пример:
int a = 1.6*1.6;
В таком случае a должен получиться 1?
(37)мне достаточно было записать double i = 3 / 15; и я получал нужный результат, может я ему принудительно указывал это сделать, уже не помню, в параметрах компиляции, сейчас он намного строже стал
я перед этим писал что компилятор приводит к максимальному типу все операнды
Вот это не совсем верно. Все операнды приводятся к наибольшему из участвующих в операции. Если оба операнда типа int, то и будет тип int.
Если один из операндов типа int, а второй типа double, то оба будут приведены к типу double.
1. а какая разница? сразу результат присваивается или вычисляется? все эти простые вычисления за десяток тиков тактовой частоты расчитываются, т.е. какая-то лиллионная доля секунды.
2.нвверно, все-таки зависит от транслятора, многие трансляторы делают предвычисления, и даже с переменными если в них были помещениы константы/числа
3.вообще эта ветка форума по 1С, тут даже как это все в там ПИ код 1С транслируется не заморачиваются, не то что там с ассемблером., .
(6) Точность результата до присваивания ограничена только разрядностью cpu/fpu, после - разрядностью/стандартом переменной.
Вместо float вы могли бы взять 8-биное, выражение, записанное в одну строку, был бы тот же.
(4)Константы с плавающей запятой без суффикса f, F, l или L относятся к типу double. Если суффикс представлен буквой f или F, константа относится к типу float. Если суффикс представлен буквой l или L, константа относится к типу long double.
С++ для начинающих. Обзор компиляторов
Существует множество компиляторов с языка C++, которые можно использовать для создания исполняемого кода под разные платформы. Проекты компиляторов можно классифицировать по следующим критериям.
Чтобы увидеть результат препроцессинга можно воспользоваться опцией...
ссылка
Я занимался Си ещё во времена MS DOS. Помню что многое зависит от компилятора.
Если компилятор компилирует "в лоб", то он напишет примерно следующие команды:
записать в регистр процессора число 3
умножить содержимое регистра на 4
разделить полученный результат на 6
добавить к результату 1 (или выполнить инкремент)
занести результат в ячейку памяти, в которой хранится f.
Более продвинутый компилятор еще на этапе компиляции вычислит выражение и запишет его в f.
Как-то так.
Скажем так хороший компилятор обязан оптимизировать программный код с целью ускорения его работы.
Если приведенный вами расчет провести на этапе компиляции и заменить на подстановку готового результата то это будет хорошим примером оптимизации.
Но не каждый компилятор является хорошим поэтому и не каждый выполнит такую оптимизацию.
Поэтому если вы пишете программу в которой скорость является критичной и если тем более вы даже не знаете какой компилятор в итоге это будет обрабатывать то лучше не надеяться на компилятор и подставить рассчитанное значение.
Для обычных пользовательских программ оставлять такую оптимизацию на откуп компилятору и оставлять расчет в наглядном виде для упрощения чтения кода и дальнейшей корректировки программы общепринято и вполне допустимо.