Будет ли a + b + c работать так: a + c + b? - PullRequest
1 голос
/ 07 апреля 2011

Как все мы знаем: последовательность оценки определяется приоритетом и ассоциативностью.Для этого примера ассоциативность определила, что a + b, затем результат плюс c.Это то, что делает совместимый с ANSI C компилятор (исключая оптимизацию). Но будет ли он оцениваться, как описано выше в заголовке?В каком компиляторе?В K & R C?

Ответы [ 6 ]

4 голосов
/ 07 апреля 2011
2 голосов
/ 07 апреля 2011

Компилятор свободен переставлять вещи, если конечный результат тот же.

Например:

1 + b + 1

Может быть легко преобразовано в:

b + 2
1 голос
/ 07 апреля 2011

n1256 :

6.5 Выражения
...
3 Группировка операторов и операндов указывается синтаксисом. 74) За исключением случаев, указанных далее (для вызовов функций (), &&, ||, ?: и операторов запятой), порядок вычисления подвыражений и порядок, в которомПроисходящие побочные эффекты не определены .
...
74) Синтаксис определяет приоритет операторов при вычислении выражения, который совпадает с порядком старших основных подпунктов этого подпункта, причем сначала самый высокий приоритет.Так, например, выражения, разрешенные в качестве операндов бинарного оператора + (6.5.6), являются выражениями, определенными в 6.5.1–6.6.6.Исключениями являются выражения приведения (6.5.4) в качестве операндов унарных операторов (6.5.3) и операнд, содержащийся между любыми из следующих пар операторов: группирующие скобки () (6.5.1), подписывающие скобки [](6.5.2.1), круглые скобки вызова функции () (6.5.2.2) и условный оператор ?: (6.5.15).

В каждом главном подпункте операторы имеют одинаковый приоритет.Ассоциативность влево или вправо указывается в каждом подпункте синтаксисом для обсуждаемых в нем выражений.

Акцент мой.Выражение a + b + c будет оцениваться как (a + b) + c;то есть результат из c будет добавлен к результату из a + ba, и b должны быть оценены до того, как a + b могут быть оценены, но a, b и c могут быть оценены в любом порядке.

1 голос
/ 07 апреля 2011

Структура уравнения в математических терминах (в a+(b*c) мы говорим о b*c, который оценивается «первым»), не обязательно связано с порядком, компилятор будет оценивать аргументы

Фактический порядокисполнение в этом случае не определено IIRC.C только гарантирует, что порядок выражений, разделенных точками последовательности, останется неизменным, а оператор + не является точкой последовательности.

Большинство компиляторов будут делать то, что вы ожидаете, - генерируя код, который будет оцениватьа потом б то с

0 голосов
/ 07 апреля 2011

Я постараюсь выделить разницу между тем, что вы считаете порядком оценки , и тем, что компилятор считает.

Математически мы говорим, что в выражении a + b * c умножение вычисляется перед сложением. Конечно, это должно быть потому, что мы должны знать, что добавить к a.

Однако компилятору не обязательно нужно учитывать выражение b * c, прежде чем он вычислит a. Вы можете подумать, что, поскольку умножение имеет более высокий приоритет, компилятор сначала будет смотреть на эту часть выражения. На самом деле, нет никакой гарантии относительно того, что компилятор решит сделать первым. Он может сначала оценить a, либо b, либо c. Это поведение не указано по стандарту.

Чтобы продемонстрировать, давайте посмотрим на следующий код:

#include <iostream>

int f() { std::cout << "f\n"; return 1; }
int g() { std::cout << "g\n"; return 2; }
int h() { std::cout << "h\n"; return 3; }

int main(int argc, const char* argv[])
{
  int x = f() + g() * h();
  std::cout << x << std::endl;
  return 0;
}

Каждая функция, f(), g() и h(), просто выводит имя функции на стандартный вывод и затем возвращает 1, 2 или 3 соответственно.

Когда программа запускается, мы инициализируем переменную x, которая будет f() + g() * h(). Это именно то выражение, на которое мы смотрели ранее. Ответ, конечно, будет 7. Теперь, наивно, вы можете предположить, что умножение произойдет первым, поэтому оно пойдет туда и будет делать g(), затем умножить его на h(), затем оно будет делать f() и добавьте его к предыдущему результату.

На самом деле, компиляция с помощью GCC 4.4.5 показывает, что функции выполняются в том порядке, в котором они появляются в выражении: f(), затем g(), затем h(). Это не то, что обязательно произойдет одинаково во всех компиляторах. Это полностью зависит от того, как компилятор хочет это сделать.

Если вы выполняете операции, которые являются ассоциативными или коммутативными, то компилятор также может свободно переключаться между математическими группировками в выражении, но только если , результат будет точно тот же самый. Компилятор должен быть осторожен, чтобы не делать никаких перегруппировок, которые могут вызвать переполнение, которое в любом случае не произошло бы. Пока результат соответствует стандарту, компилятор может делать то, что ему нравится.

0 голосов
/ 07 апреля 2011
a + b + c == c + b + a

Порядок не имеет значения.

Это называется приоритет оператора

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...