WedX - журнал о программировании и компьютерных науках

В C / C ++ x [i] * y [i ++] всегда равно x [i] * y [i] [duplicate]

Возможный дубликат:
Может ли кто-нибудь объяснить это неопределенное поведение (i = i ++ + ++ i, i = i ++ и т.д.)
увеличивать значения в printf

У меня есть два двойных массива x и y и целое число i. У меня вопрос, есть ли утверждение:

double res = x[i] * y[i++];

всегда равно заявлению:

double res = x[i] * y[i];
i++;

Возможно ли, что некоторые компиляторы превратят x[i] * y[i++] в y[i++] * x[i], что, очевидно, даст другой результат?


  • Почему это имеет значение? Если вам нужен конкретный порядок, просто напишите его в таком порядке. 05.12.2012
  • @BoPersson. Думал написать объяснение, зачем мне это нужно, но не хотел портить вопрос. Вскоре мне нужно ускорить double vectors_dot_product(double *x, double *y, int n); функцию, и я обнаружил, что x[i] * y[i++] + x[i] * y[i++] + ...; быстрее, чем x[i] * y[i] + x[i+1] * y[i+1] + ...; 05.12.2012

Ответы:


1

Нет - x[i] + y[i++] имеет неопределенное поведение. Вы изменяете значение i, а также используете значение i без промежуточной точки последовательности, что дает неопределенное поведение 1.


  1. В C ++ 11 стандарт исключил терминологию «точки последовательности», но эффект остался тем же - эти две точки не упорядочены по отношению друг к другу.
05.12.2012
  • +1 первый ответ на правильном языке. 05.12.2012
  • Это не имеет ничего общего с коммутативностью оператора умножения. Если операция была x[i] - y[i++] (которую нельзя отменить), поведение i в этой ситуации все равно будет неопределенным. 05.12.2012

  • 2

    Нет, когда происходит приращение, он не определен.

    05.12.2012
  • Не только тогда, когда происходит приращение. Поведение полностью не определено: оно изменяет i и считывает его значение без промежуточной точки последовательности. 05.12.2012
  • @Pete: Отлично, когда разносчик пиццы появится у меня на пороге? ;) 05.12.2012
  • @FredOverflow - спросите поставщика компилятора. 05.12.2012

  • 3

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

    05.12.2012
  • Интересно, что вы, как никто другой, не упомянули бы тот факт, что C ++ 11 больше не использует точку последовательности. :-) 05.12.2012
  • @JerryCoffin - иногда лучше все упрощать. 05.12.2012
  • +1. Есть что сказать о простоте отказа от веры всем входящим сюда. 05.12.2012

  • 4

    No,

    значение i ++ + i ++ равно undefined в C и C++.

    если вы дважды читаете переменную в выражении, в которое вы ее также записываете, результат не определен. Не делай этого. Другой пример:

    v[i] = i++;
    

    Неопределенный означает, что он ЗАВИСИТ ОТ КОМПИЛЯТОРА.
    Некоторые компиляторы могут предупреждать вас также как неопределенные из-за порядка оценки. Очень хороший справочник по C ++

    1 https://www.stroustrup.com/bs_faq2.html#rating-order.

    05.12.2012
  • По-прежнему нужно немного поработать - v[i] = i++; не определен, хотя он может вообще не включать никаких функций или передаваемых аргументов. 05.12.2012
  • @GrijeshChauhan, спасибо за ссылку. 05.12.2012
  • @Serg: Добро пожаловать, serg! Рад, если смогу помочь :) 05.12.2012
  • @Jerry Coffin: Спасибо за информацию ... Об этом упоминается в предоставленной мной ссылке. 05.12.2012
  • @GrijeshChauhan - извините за нагромождение, но это не порядка оценки. Порядок оценки аргументов функции не указан, что означает, что он зависит от компилятора: компилятор может произвольно выбирать порядок. Здесь нет аргументов функции, которые нужно оценивать. Поведение undefined, что означает, что все ставки отключены. В некотором смысле он зависит от компилятора, поскольку он, очевидно, зависит от кода, который генерирует компилятор, но код, который генерирует компилятор (если это так ...), не должен делать ничего разумного. 05.12.2012
  • Новые материалы

    Как создать диаграмму градиентной кисти с помощью D3.js
    Резюме: Из этого туториала Вы узнаете, как добавить градиентную кисть к диаграмме с областями в D3.js. Мы добавим градиент к значениям SVG и применим градиент в качестве заливки к диаграмме с..

    Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что это выглядит сложно…
    Просто начните и учитесь самостоятельно Я хотел выучить язык программирования MVC4, но не мог выучить его раньше, потому что он кажется мне сложным, и я бросил его. Это в основном инструмент..

    Лицензии с открытым исходным кодом: руководство для разработчиков и создателей
    В динамичном мире разработки программного обеспечения открытый исходный код стал мощной парадигмой, способствующей сотрудничеству, инновациям и прогрессу, движимому сообществом. В основе..

    Объяснение документов 02: BERT
    BERT представил двухступенчатую структуру обучения: предварительное обучение и тонкая настройка. Во время предварительного обучения модель обучается на неразмеченных данных с помощью..

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..


    Для любых предложений по сайту: [email protected]