Czym dokładnie jest typ C / C++?

Czym dokładnie jest typ C / C++? Jak kompilator sprawdza, czy potrzebny jest jawny typ (i poprawny)? Czy porównuje przestrzeń wymaganą dla wartości? Jeśli mam na przykład:

int a;
double b = 15.0;
a = (int) b;

Jeśli dobrze pamiętam, Podwójna wartość wymaga więcej miejsca (8 bajtów?!) niż liczba całkowita (4 bajty). A wewnętrzna reprezentacja obu jest zupełnie inna (dopełniacz na dwóch/mantissa). Więc co się dzieje wewnętrznie? Przykład tutaj jest dość prosty, ale w C / C++ istnieje wiele typówkasty.

Skąd kompilator (lub programista) wie, czy mogę wrzucić np. FOO do paska?

Author: Amjad Rehman A, 2011-09-26

4 answers

Typ odlewu jest w zasadzie konwersją z jednego typu do drugiego. Może być niejawne (tzn. wykonywane automatycznie przez kompilator, być może tracąc informacje w procesie) lub jawne (tzn. określone przez programistę w kodzie). Przestrzeń zajmowana przez typy ma drugorzędne znaczenie. Ważniejsze jest zastosowanie (a czasem convenice) konwersji.

Możliwe jest, że konwersje niejawne utracą informacje, znaki mogą zostać utracone / zdobyte, a przepełnienie / zanik może występuje. Kompilator nie ochroni Cię przed tymi zdarzeniami, z wyjątkiem Ostrzeżenia generowanego podczas kompilacji. Krojenie może również wystąpić, gdy typ Pochodny jest niejawnie konwertowany na typ bazowy (przez wartość).

Dla konwersji, które mogą być wręcz niebezpieczne (np. z typu bazowego na typ Pochodny), standard C++ wymaga jawnej obsady. Nie tylko to, ale oferuje bardziej restrykcyjne, wyraźne rzuty, takie jak static_cast, dynamic_cast, reinterpret_cast, i const_cast, z których każdy dodatkowo ogranicza jawny rzut tylko na podzbiór możliwych konwersji, zmniejszając potencjał błędów odlewania.

Poprawne konwersje, zarówno implicit, jak i explict są definiowane przez standardy C / C++, chociaż w C++ programista ma możliwość rozszerzenia konwersji dla typów zdefiniowanych przez użytkownika, zarówno implicit, jak i explicit, poprzez użycie konstruktorów i operatorów przeciążonych (cast).

Pełne Zasady, dla których rzuty są dozwolone przez normy, a które nie są mogą uzyskać całkiem zawiłe. Starałem się wiernie przedstawić nieco zwięzłe podsumowanie niektórych z tych zasad w niniejszej odpowiedzi. Jeśli jesteś naprawdę zainteresowany tym, co jest, a czego nie wolno, gorąco zachęcam do odwiedzenia standardów i przeczytania odpowiednich sekcji dotyczących konwersji typów.

 31
Author: Michael Goldshteyn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-26 19:12:51

Chcę tylko wspomnieć o czymś często pomijanym:

  • rzut zawsze tworzy tymczasowy typ docelowy (chociaż jeśli typ docelowy jest odniesieniem, nie zauważysz).
To może być ważne. Na przykład:
#include <iostream>

void change_one_print_other( int& a, const int& b )
{
    a = 0;
    std::cout << b << "\n";
}

int main(void)
{
    int x = 5, y = 5;

    change_one_print_other(x, x);
    change_one_print_other(y, static_cast<int>(y));
}
Ta Obsada wygląda na bezużyteczną. Ale wygląd może być mylący.
 8
Author: Ben Voigt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-14 13:17:39

Istnieją pewne typy, które kompilator wie, jak to zrobić bezwarunkowo - double to int jest jednym z nich. Po prostu upuszcza część dziesiętną. Wewnętrzna reprezentacja jest konwertowana jako część procesu, dzięki czemu przypisanie działa poprawnie.

Zauważ, że wartości są zbyt duże, aby można je było poprawnie przekonwertować. Nie pamiętam jakie są zasady w tej sprawie; może to pozostawić w gestii kompilatora.

 1
Author: Mark Ransom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-26 17:37:45

Zrób mały program C z kodu i postępuj zgodnie z instrukcjami w Jak zmusić GCC do wygenerowania kodu assembly aby zobaczyć jak kompilator wykonuje Typ cast.

 1
Author: ott--,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-09-26 18:17:15