2013-06-20 7 views
32

W sekcji 10.5.1 nowej książki Stroustrupa "Język programowania C++ - wydanie czwarte" mówi on, że przed wykonaniem operacji arytmetycznej, integralna promocja jest używana do tworzenia intów z krótszych typów całkowitych, podobnie jak zmiennoprzecinkowe promocja służy do tworzenia podwładnych.Promocja zmiennoprzecinkowa: stroustrup vs kompilator - kto ma rację?

Potwierdzałem pierwsze żądanie z następującego kodu:

#include <iostream> 
#include <typeinfo> 

int main() 
{ 
    short a; 
    short b; 
    std::cout << typeid(a + b).name() << std::endl; 
} 

Ten wynik "int" z VC++ i "I" na GCC.

Ale sprawdzając je za pomocą pływaków zamiast szortów, wyjście jest nadal „pływak” lub „f”:

#include <iostream> 
#include <typeinfo> 

int main() 
{ 
    float a; 
    float b; 
    std::cout << typeid(a + b).name() << std::endl; 
} 

Według Stroustrup nie istnieją wyjątki od zmiennoprzecinkowej promocyjnej-reguły, więc oczekiwano "podwójny" lub "d" jako wynik.

Czy wspomniana sekcja dotycząca promocji jest błędna lub niejasna? Czy jest jakaś różnica w C++ 98 i C++ 11 w zakresie promocji typu?

+2

Uważam, że awans z 'float' na' double' występuje tylko w przypadku * mixed * arithmethic; to znaczy, kiedy dodajemy 'float' i' double' razem, 'float' jest najpierw promowany przed przeprowadzeniem dodawania. Jesteś pewien, że tak nie jest? –

+1

'int' to" minimalny poziom "dla całkowej arytmetyki w C++, a' float' to "minimalny poziom" dla arytmetyki zmiennoprzecinkowej. – Xeo

+1

Właśnie zacytowałem książkę. Wyraźnie mówi, że pływaki awansują do debli. Nie robi też ani słowa "arytmetyka mieszana", tylko "przed operacją arytmetyczną". – kiba

Odpowiedz

29

Nie wiem, co dokładnie mówi książka Stroustrupa, ale zgodnie ze standardem, float s nie zostaną w tym przypadku przekonwertowane na double. Przed nałożeniem większość arytmetyczne operatorów binarnego zwykłe arytmetyczne konwersji opisane w 5p9 są stosowane:

  • Jeśli albo operandów jest określania zakresów typu wyliczenia (7,2) nie są wykonywane konwersji; jeśli drugi operand nie ma tego samego typu, wyrażenie jest źle sformułowane.
  • Jeśli jeden z argumentów jest typu długiego podwójny, drugi zostanie przekształcony na długi podwójny.
  • W przeciwnym razie, jeśli jeden z argumentów jest podwójny, drugi zostanie przekonwertowany na podwójny.
  • W przeciwnym razie, jeśli dowolny operand jest zmiennoprzecinkowy, drugi będzie konwertowany na zmienny.
  • W przeciwnym razie, całkowe promocje (4.5) będą wykonywane na obu operandach. [...]

Integralne promocje są, co powoduje, że dwa short S być przekształcony int s. Ale dwie wartości float s nie zostaną przekonwertowane na double s zgodnie z tymi regułami. Jeśli dodasz float do double, float zostanie przekonwertowany na double.

Powyższe pochodzi z C++ 11. C++ 03 zawiera te same reguły, z wyjątkiem tej odnoszącej się do wyliczeń o zakresie.

+0

Wydaje się to pasować do doświadczenia OP. Powiedziałbym, że Standard ma rację. Może literówka w książce? +1. –

+0

'4,6 zmiennoprzecinkowej Promocja [conv.fpprom] prvalue typu pływaka można przekształcić do prvalue typu dwukrotnie . Wartość nie ulega zmianie. Konwersja ta jest nazywana zmiennoprzecinkowych promocji .' [pochodzi od tej normy] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf) - czy to jest inny? – fiscblog

+0

Więc nie ma domyślnej promocji typu "pływającego"? Stroustrup mówi, że celem tych promocji jest doprowadzenie operandów do "naturalnego" rozmiaru dla operacji arytmetycznych. "Naturalny" typ zmiennoprzecinkowy jest podwójny, więc wydaje się być błędem w książce. – kiba

5

W międzyczasie Stroustrup wydaje się rozpoznawać, że zdanie odwołania nie jest poprawne lub przynajmniej wprowadza w błąd. Usunął zdanie dotyczące promocji zmiennoprzecinkowej z sekcji 10.5.1.

proszę zobaczyć errata z 3 druk 4. edycji na stronie internetowej Stroustrupa za:

pg 267: s/Podobnie zmiennoprzecinkową promocja służy do tworzenia podwójnych z pływaków //

(Uwaga: wyrażenie s/regexp/wymiana/jest podobny do sed unix semantykę narzędzie to wyszukuje wzorca regexp i zastępuje go wymiany nr.. rzecz w naszym przypadku.)

+1

To powinien być komentarz, a nie odpowiedź. – EWit

+0

@EWit: Tom8128 nie zdobył [uprawnienia do komentowania] (http://stackoverflow.com/help/privileges/comment). – Cornstalks

+0

@ Tom8128: Otrzymałem +1 od ciebie, ponieważ masz rację, dodałem komentarz do dyskusji pod tym pytaniem, aby wspomnieć o erracie. Sugeruję jednak, abyś zmodyfikował swoje pytanie, dołączając link do erraty i odpowiedni cytat z niego oraz małe wyjaśnienie. W tej sytuacji odpowiedź jest krótka i wymaga pewnego rozszerzenia, aby była świetna. W przyszłości, gdy uzyskasz przywilej komentowania, takie rzeczy powinny być komentarzami. Dlatego proponuję rozwinąć tę odpowiedź: zmienić ją w właściwą odpowiedź. – Cornstalks

Powiązane problemy