2013-07-15 27 views
6

Nie jestem pewien co do gwarancji wykonania dla potrójnego operatora C/C++.
Na przykład jeśli mam podany adres i wartość logiczną, która mówi, jeśli adres jest dobre do czytania można łatwo uniknąć źle odczytuje za pomocą if/else:Warunki wykonywania potrójnego operatora C++

int foo(const bool addressGood, const int* ptr) { 
    if (addressGood) { return ptr[0]; } 
    else { return 0; } 
} 

Czy operator trójskładnikowych (?:) Gwarancja jednak, że ptr nie będzie dostępny, chyba że addressGood jest prawdziwy?
A może optymalizujący kompilator generuje kod, który uzyskuje dostęp do ptr w każdym przypadku (prawdopodobnie powodując awarię programu), przechowuje wartość w rejestrze pośrednim i używa warunkowego przypisania do wdrożenia operatora trójskładnikowego?

int foo(const bool addressGood, const int* ptr) { 
    // Not sure about ptr access conditions here. 
    return (addressGood) ? ptr[0] : 0; 
} 

Dzięki.

+0

AFAIK, tak, nie powinien oceniać drugiego oddziału. – chris

+0

Styl projektu: API naprawdę nie powinno mieć "addressGood". Kanoniczna reprezentacja złego adresu to "0". To znaczy. 'int foo (const const int * ptr) {return ptr? * ptr: 0; } ' – MSalters

+0

Nie wiem, czy' const const int * 'naprawdę ma sens. – rsp1984

Odpowiedz

8

Tak, standard gwarantuje, że ptr jest dostępny tylko po spełnieniu warunku addressGood. Zobacz temat this answer na temat, który cytuje standard:

Grupa wyrażeń warunkowych od prawej do lewej. Pierwsze wyrażenie jest konwertowane kontekstowo na bool (Rozdział 4). Jest oceniany, a jeśli jest prawdziwy, wynikiem wyrażenia warunkowego jest wartość drugiego wyrażenia, w przeciwnym razie wartość trzeciego wyrażenia. Oceniane jest tylko jedno z wyrażeń drugiego i trzeciego. Każda obliczona wartość i skutek uboczny związany z pierwszym wyrażeniem są sekwencjonowane przed każdym obliczeniem wartości i efektem ubocznym związanym z drugim lub trzecim wyrażeniem. (Standard C++ 11, ustęp 5,16/1)

0

C++ 11/[expr.cond]/1

Conditional expressions group right-to-left. The first expression is contextually converted to bool (Clause 4). 
It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, 
otherwise that of the third expression. Only one of the second and third expressions is evaluated. Every value 
computation and side effect associated with the first expression is sequenced before every value computation 
and side effect associated with the second or third expression 
1

warunkowych (potrójne) gwarantuje, operator tylko ocenia drugi operand, jeśli pierwszy operand porównuje nierówność z 0 i ocenia tylko trzeci argument, jeśli pierwszy operand jest równy 0. Oznacza to, że kod jest bezpieczny.

Po ocenie pierwszego operandu istnieje również punkt sekwencji.

Nawiasem mówiąc, nie potrzebujesz paranthezy - addressGood ? ptr[0] : 0 też jest w porządku.

+0

Dobra rada z parantezami. Piszę je dla spójności, ale dzięki za wskazanie. – rsp1984

1

Powiedziałbym, oprócz odpowiedzi, że „Tak, to jest gwarantowana przez C++ standard”:

Proszę użyć pierwszego formularza. DUŻO wyraźniej, co próbujesz osiągnąć.

Mogę prawie zagwarantować, że każdy rozsądny kompilator (przy minimalnej optymalizacji) generuje dokładnie ten sam kod dla obu przykładów.

Podczas gdy dobrze jest wiedzieć, że obie te formy osiągają tę samą "ochronę", zdecydowanie preferowane jest użycie formy, która jest najbardziej czytelna.

Oznacza to również, że nie trzeba pisać komentarza wyjaśniającego, że jest on bezpieczny z powodu akapitu takiego i takiego w standardzie C++, co powoduje, że obie zajmują taką samą ilość przestrzeni kodu - ponieważ gdyby nie " Jeśli wiesz o tym wcześniej, możesz polegać na kimś innym, nie wiedząc, że jest to bezpieczne, a następnie spędzić następne pół godziny znajdując odpowiedź przez Google i uruchamiając ten wątek lub ponownie zadając pytanie!

Powiązane problemy