Wynik programu

0
int p[]={1,3,3,4,5};
printf("%d %d", (*p),  (*p)++);

Ktoś powie mi czemu wynikiem tego programu jest 2 1 ?
Chyba czegoś tu nie rozumiem

5

C++ nie precyzuje, w jakiej kolejności argumenty funkcji są ewaluowane, więc w tym przypadku kolejność zapewne jest:

  1. (*p)++ co daje liczbę 1 oraz zmienia wartość pierwszego elementu tablicy na 2
  2. (*p) wypisuje pierwszy element tablicy, czyli teraz już 2
3

To jest UB.

Wynik programu nie ma w tym wypadku znaczenia, nie możesz tak robić przy tej samej zmiennej. Jakby to były rózne elemkenty array to by było ok.

0

skompiluj/zobacz wyniki z printf("%d %d", (*p)++, (*p));

Przecież znamy wyniki (jedną wersję).

Skąd kompilator ma wiedzieć czy ma najpierw inkrementować a potem użyć kolejnej zmiennej czy użyć obu zmiennych a potem inkrementować czy bla bla,. UB

Standard pozwala kompilatorowi na wybranie jednej wygodnej mu kolejności ewaluacji parametru, przy czym ewaluacje różnych parametrów nie "zaziębiają się".
http://en.cppreference.com/w/cpp/language/eval_order

If A is not sequenced before B and B is not sequenced before A, then two possibilities exist:

  • evaluations of A and B are unsequenced: they may be performed in any order and may overlap (within a single thread of execution, the compiler may interleave the CPU instructions that comprise A and B)
  • evaluations of A and B are indeterminately sequenced: they may be performed in any order but may not overlap: either A will be complete before B, or B will be complete before A. The order may be the opposite the next time the same expression is evaluated.
  1. In a function call, value computations and side effects of the initialization of every parameter are indeterminately sequenced with respect to value computations and side effects of any other parameter.</del>
2

To zdecydownie UB.

https://timsong-cpp.github.io/cppwp/n4140/intro.execution#15

If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent ([intro.multithread]), the behavior is undefined.

0

Interesujące, standard rzeczywiście określa:

[ Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note ]

co jawnie zaprzecza

  1. In a function call, value computations and side effects of the initialization of every parameter are indeterminately sequenced with respect to value computations and side effects of any other parameter.

Oczywiście standard ma ostatnie słowo, ale czy cppreference popełniło taką oczywistą gafę, czy tamto zdanie trzeba inaczej zrozumieć?

2

W C++17 zmienili zasady, więc strzelałbym, że poprawili bez informowania, że to since [c++17]. Np. stary argument za make_shared:

foo(shared_ptr<bar>(new bar), shared_ptr<bar>(new bar));

Od 17 jest w 100% poprawny i nie zawiera leaków, bo parametry i ich side-effecty są inderminately sequenced.

http://eel.is/c++draft/expr.call#5

The postfix-expression is sequenced before each expression in the expression-list and any default argument. The initialization of a parameter, including every associated value computation and side effect, is indeterminately sequenced with respect to that of any other parameter.

W 14:

[ Note: Such initializations are indeterminately sequenced with respect to each other ([intro.execution]) — end note ]

Pomijając już nitpick, że notes/footnotes/examples nie definiują standardu, nie ma tu ani słowa o side-efektach. A, co jest dość zabawne (przynajmniej dla mnie), w wyrażeniu a=2 efektem ubocznym jest zmiana wartości a.

1 użytkowników online, w tym zalogowanych: 0, gości: 1