Порядок операций для преинкремента и постинкремента в аргументе функции? [дубликат]

11
задан Eric Leschinski 24 July 2013 в 17:04
поделиться

3 ответа

Последовательность оценки унарного оператора для функции:

#include <stdio.h>

void xyz(int x, int y) {
    printf("x:%d y:%d ", x, y);
}

main() {
    int a;
    a=1;    xyz(++a, a);        printf("a:%d\n", a);
    a=1;    xyz(a, a++);        printf("a:%d\n", a);
    a=1;    xyz(++a, a++);      printf("a:%d\n", a);
}

выведет

x:2 y:2 a:2
x:2 y:1 a:2
x:3 y:1 a:3

В моей системе. Это указывает на то, что второй параметр функции оценивается первым. Не следует полагаться на порядок оценки параметров функции. Он не определен, поэтому в разных системах он будет отличаться.

Хорошая работа по поиску отличного примера такого поведения.

1
ответ дан 3 December 2019 в 01:38
поделиться

Что ж, есть две вещи, которые следует учитывать в вашем примере кода:

  1. Порядок оценки аргументов функции не указан, поэтому, ++ a или ] a ++ вычисляется первым, это зависит от реализации.
  2. Изменение значения a более одного раза без точки последовательности между изменениями приводит к неопределенному поведению. Итак, результаты вашего кода не определены.

Если мы упростим ваш код и удалим неопределенное и неопределенное поведение, то мы сможем ответить на вопрос:

void xyz(int x) { }

int a = 1;
xyz(a++); // 1 is passed to xyz, then a is incremented to be 2

int a = 1;
xyz(++a); // a is incremented to be 2, then that 2 is passed to xyz
28
ответ дан 3 December 2019 в 01:38
поделиться

Цитирую Kernighan & Ritchie, глава 2.12:

Порядок, в котором аргументы функции не определен, поэтому оператор

printf("%d %d\n", ++n, power(2, n)); /* WRONG */

может дать разные результаты в разными компиляторами, в зависимости от того увеличивается ли n перед вызовом power вызывается. Решение, конечно же, заключается в том, чтобы написать

++n;
printf("%d %d\n", n, power(2, n));

Вызовы функций, вложенные операторы присваивания вызовы функций, вложенные операторы присваивания, а также операторы инкремента и операторы инкремента и декремента вызывают ``побочные эффекты" - некоторые переменные изменяются как побочный продукт оценки выражения. В любом выражении включающем побочные эффекты, могут быть тонкие зависимости от порядка в котором переменные, участвующие в выражении, обновляются. Одна из неприятных ситуации является выражение

a[i] = i++;

Вопрос в том, является ли подстрочный индекс является старым значением i или новым. Компиляторы могут интерпретировать это по-разному, и генерировать различные ответы в зависимости от их интерпретации. Стандарт намеренно оставляет большинство таких вопросов неопределенными. Когда побочные эффекты (присвоение переменным) происходят внутри выражения, остается на усмотрение компилятора, поскольку наилучший порядок сильно зависит от архитектуры машины архитектуры. (Стандарт действительно указывает, что все побочные эффекты для аргументов вступают в силу до того, как до вызова функции, но это не помочь в приведенном выше вызове printf). Мораль мораль в том, что писать код, который зависит от порядка оценки, является плохая практика программирования на любом языке. Естественно, необходимо знать, каких вещей следует избегать, но если вы не знаете, как они выполняются на различных машинах, у вас не возникнет соблазна воспользоваться преимуществами конкретной реализацией.

10
ответ дан 3 December 2019 в 01:38
поделиться
Другие вопросы по тегам:

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