Вопрос по c, sequence-points, c++ – Откуда берутся точки последовательности?

9

Я знаю, что писать что-то вроде

++a = a++;

Не только не читается, но и нарушает точки последовательности c / c ++.

Откуда эти ограничения? Как можно увидеть эти «проблемы»? прежде чем найти их как ошибки?

error: operation on 'a' may be undefined [-Werror=sequence-point] - Ах, спасибо, удобный компилятор. chris
@ArturMarianek: этоlanguage проблема. Язык может решить конкретный порядок оценки, и компилятор должен будет обеспечить это. Это совершенно не связано с оборудованием. David Rodríguez - dribeas
Ну, все же, это ограничение дизайна языка или, скорее, ограничение компьютера (CPU), общее для любого языка? Artur Marianek
Включите все свои предупреждения и скомпилируйте и обработайте предупреждения как логические ошибки, и вам не нужно беспокоиться об этом:-Werror -Wall -Wextra -ansi -pedantic Martin York

Ваш Ответ

4   ответа
8

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

Однако вы, как правило, только когда-либо нарушаете требования точки последовательности, если вы пишете «интересно». код, такой как ваш пример. Стандарт языкаcould налагать определенные ограничения на код, такой как этот (что и делают языки, такие как Java), но нет большого преимущества и потенциального недостатка в предотвращении определенных типов оптимизации.

1. The terminology has changed slightly in C++11, but the principle is still largely the same, I think.

Спасибо за ответ. Хотел бы я, чтобы "принять" здесь много ответов;) Artur Marianek
Недавно я ответил на вопрос о различиях между C ++ 98 и C ++ 11:stackoverflow.com/a/10655884/365496
-1

problems' before finding them as bugs?

Они происходят из-за неоднозначности (или свободы изменения) порядка операций во время выполнения.

Для вашего примера:

++a = a++;

язык оставляет неопределенным, должно ли предварительное увеличение значения l происходить до или после последующего увеличения значения r. Добавление ограничения здесь повлечет за собой значительные расходы; какова общая выгода? Что является ясным, очевидным способом, которым этот пример кода «должен»? вести себя?

Чтобы повысить производительность, порядок операций в программе может быть изменен (в строгих пределах) компилятором и / или процессором.

Overly ограничивающий порядок выполнения будет:

Make it more difficult to implement C/C++ for different target architectures Add complexity to the language specification Cut performance (in return for what gain?) Prevent many compile-time optimizations, cutting performance Require disabling pipelining and hardware reordering during execution, again cutting performance Perhaps break existing code

Давайте посмотрим на ограничение порядка выполнения для другого примера кода:

a = b++ + ++c - --d - e--;

Предположим, что доступно только ограниченное количество регистров и что некоторые из переменных («d» и «e») находятся в регистрах, а некоторые - нет. Строго ограничивающий порядок выполнения (скажем, слева направо) может потребовать:

Discard 'd' from registers Discard 'e' from registers Load 'b' Save its initial value as 'b,original' Increment 'b' (might be non-trivial for some data types) Store modified 'b' Reload 'b,original' Load 'c' Increment 'c' Save updated 'c' Add 'b,original' + 'c' and save as, partial result etc. etc.

Хотя, если разрешено, например, обрабатывать & d; и "е"; сначала и увеличивать «b»; чуть позже компилятор может значительно сократить количество шагов и повысить производительность.

Кодundefined behaviour что означает что угодно, что бы ни случилось. Не является «неопределенным», произойдет ли [вариант 1] или [вариант 2].
@ M.M Да, мы и компилятор согласны с тем, что пример кода OP будет иметь неопределенное поведение. Однако то, что ОПasked был, "Как можно увидеть эти" проблемы " прежде чем найти их в качестве ошибок? & quot; Я хотел помочь читателю понять,why это неопределенное поведение,why Последовательности выполнения не указаны подробно, потому что это понимание приводит к возможности увидеть, где исполнение может быть переупорядочено, и способности выявлять такие проблемы.
Я бы порекомендовал изменить ваше предложение, которое включает в себя "неопределенный [вариант 1] или [вариант 2]". Такжеa является lvalue в обоих случаях в++a = a++, он не должен сказать «постинкремент на значение» поскольку на самом деле постинкремент может происходить только для lvalue (для встроенных типов).
9

между каждым оператором существует точка последовательности C ++ 03. Для получения дополнительной информации см.SO C ++ FAQ, Для получения дополнительной информации обращайтесь к стандарту C ++ и помните, что в стандарте C ++ 11 точки последовательности были заменены наsequenced before а такжеsequenced after связи.

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

Не пытайтесь выполнять работу компилятора: оставьте это компилятору. Ваша задача - написать код, который могут легко понять другие люди, т.е.clear code, Многократные обновления и ненужное использование операторов с побочными эффектами не совместимы с этим.

Совет: посыпатьconst почти везде возможно.

Это ограничивает возможные изменения состояния, которые должен учитывать читатель.

Спасибо за ответ. Хотел бы я, чтобы "принять" здесь много ответов;) Artur Marianek
5

How can one see those 'problems' before finding them as bugs?

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

С gcc вы можете использовать:

-Wsequence-point

который должен указать на проблемы последовательности точек. Обратите внимание, что он включен по умолчанию, если вы используете-Wall.

Конечно, лучший способ - это попытаться написать более читаемый код, который избегает точки последовательностиmis-adventures.

+1 за-Wsequence-point вариант. Я не знал об этом.
@Крис:-Wall включает его по умолчанию, как я уже упоминал.
Действительно, я неправильно это понял.
+1 за-Wsequence-point вариант. Я не знал об этом.
Спасибо за ответ. Хотел бы я, чтобы "принять" здесь много ответов;) Artur Marianek

Похожие вопросы