Dlaczego Skrót musi być konwertowany na int przed operacjami arytmetycznymi w C i C++?

Z odpowiedzi, które otrzymałem z tego pytania wynika, że C++ odziedziczył ten wymóg Konwersji short na int podczas wykonywania operacji arytmetycznych z C. Czy Mogę wybrać twój mózg tak, aby dlaczego to zostało wprowadzone w C w pierwszej kolejności? Dlaczego nie zrobić tych operacji jako short?

Na przykład (zaczerpnięte z sugestii dypa w komentarzach):

short s = 1, t = 2 ;
auto  x = s + t ;

x będzie miał Typ int .

Author: Community, 2014-06-23

4 answers

Jeśli spojrzymy na uzasadnienie dla międzynarodowych standardów-języków programowania-C w sekcji 6.3.1.8 zwykłe konwersje arytmetyczne mówi ( podkreślenie):

Reguły w standardzie dla tych konwersji są niewielkie modyfikacje tych w K & R: modyfikacje uwzględniają dodane typy i reguły zachowania wartości. Licencja Explicit została dodana do wykonywanie obliczeń w "szerszym" typie niż absolutnie konieczne, ponieważ może to czasami produkować mniejszy i szybszy kod, nie do częściej wymieniaj poprawną odpowiedź . Obliczenia mogą być również wykonywany w "węższym" typie przez regułę as if tak długo, jak ten sam uzyskuje się efekt końcowy. W celu uzyskania wartość w żądanym typie

Sekcja {[0] } z szkic standardu C99 obejmuje zwykłe przekształcenia arytmetyczne, które stosuje się do operandów wyrażeń arytmetycznych na przykład sekcja 6.5.6 operatory addytywne says:

Jeśli oba operandy mają typ arytmetyczny, to zwykła arytmetyka na nich wykonywane są konwersje.

Podobny tekst znajdujemy w sekcji 6.5.5 operatory Multiplikatywne również. W przypadku operandu krótkiego, najpierw stosuje sięliczbę całkowitą z sekcji 6.3.1.1 Boolean, characters, and integers co mówi:

Jeśli int może reprezentować wszystkie wartości typu original, wartość jest konwertowana na liczbę całkowitą; w przeciwnym razie jest konwertowana na niepodpisaną liczbę całkowitą. są to tzw. promocje całkowite .48) wszystkie inne rodzaje to / align = "left" /

Dyskusja z sekcji 6.3.1.1 uzasadnienie czy międzynarodowe standardy-języki programowania-C na integer promotions jest faktycznie bardziej interesująca, zamierzam wybiórczo cytować b/c jest zbyt długi do pełnego cytatu:

} dwa główne obozy, które można scharakteryzować jako unsigned preserving I value preserving.

[...]

Podejście unsigned preserving wzywa do promowania dwóch mniejszych niepodpisane typy do niepodpisanej liczby całkowitej. Jest to prosta zasada i daje Typ niezależny od środowiska wykonawczego.

Podejście zachowujące wartość wymaga promowanie tych typów do signed int jeśli ten typ może poprawnie reprezentować wszystkie wartości z oryginalnego typu, A w innym przypadku do promowania tych typów do niepodpisanych int. Tak więc, jeśli środowisko wykonawcze reprezentuje krótki jak coś mniejszy niż int, unsigned short staje się int; w przeciwnym razie staje się niepodpisana liczba całkowita.

Może to mieć dość nieoczekiwane wyniki w niektórych przypadkach, ponieważ niespójne zachowanie ukrytej konwersji między niepodpisanym i większym podpisem typy pokazuje, Jest wiele więcej takich przykładów. Chociaż w większości przypadków powoduje to, że operacje działają zgodnie z oczekiwaniami.

 36
Author: Shafik Yaghmour,
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
2017-05-23 11:46:57

Nie jest to cecha języka, ale ograniczenie fizycznych architektur procesorów, na których działa kod. Typer int W C jest zwykle wielkością standardowego rejestru procesora. Więcej krzemu zajmuje więcej miejsca i więcej mocy, więc w wielu przypadkach arytmetyka może być wykonana tylko na typach danych "naturalnej wielkości". Nie jest to powszechnie prawdą, ale większość architektur nadal ma to ograniczenie. Innymi słowy, przy dodawaniu dwóch liczb 8-bitowych, co tak naprawdę dzieje się w procesorze jest rodzajem 32-bitowej arytmetyki, po której następuje albo prosta maska bitowa, albo inna odpowiednia konwersja typu.

 21
Author: Phonon,
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-06-23 19:03:43

float, short i char typy są uważane przez standardowy rodzaj "typów pamięci", tzn. podzakresów, które można wykorzystać, aby zaoszczędzić trochę miejsca, ale które nie kupią ci żadnej prędkości, ponieważ ich rozmiar jest "nienaturalny"dla procesora.

Na niektórych procesorach nie jest to prawdą, ale dobre Kompilatory są na tyle inteligentne, że zauważają, że jeśli np. dodasz stałą do unsigned char i zachowasz wynik z powrotem w unsigned char, nie ma potrzeby przechodzenia przez konwersję unsigned char -> int. Na przykład z g++ kod wygenerowany dla wewnętrznej pętli

void incbuf(unsigned char *buf, int size) {
    for (int i=0; i<size; i++) {
        buf[i] = buf[i] + 1;
    }
}

Jest po prostu

.L3:
    addb    $1, (%rdi,%rax)
    addq    $1, %rax
    cmpl    %eax, %esi
    jg  .L3
.L1:

Gdzie widać, że używana jest instrukcja dodawania znaków bez znaku (addb).

To samo dzieje się, gdy wykonujesz obliczenia między krótkimi ints i przechowujesz wynik w krótkich ints.

 15
Author: 6502,
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-11-28 14:40:55

Połączone pytanie wydaje się pokrywać to całkiem dobrze: procesor po prostu nie. 32-bitowy procesor ma swoje natywne operacje arytmetyczne skonfigurowane dla 32-bitowych rejestrów. Procesor woli pracować w swoim ulubionym rozmiarze, a w przypadku takich operacji kopiowanie małej wartości do rejestru o rozmiarze natywnym jest tanie. (Dla architektury x86 rejestry 32-bitowe są nazwane tak, jakby były rozszerzonymi wersjami rejestrów 16-bitowych (eax do ax, ebx do bx, itd.); patrz x86 integer instrukcje ).

Dla niektórych bardzo powszechnych operacji, szczególnie arytmetyki wektorowej / zmiennoprzecinkowej, mogą istnieć specjalistyczne instrukcje, które operują na innym typie lub rozmiarze rejestru. Dla czegoś takiego jak krótki, padding Z (do) 16 bitów zer ma bardzo mały koszt wydajności i dodanie wyspecjalizowanych instrukcji prawdopodobnie nie jest warte czasu lub miejsca na matrycy (jeśli chcesz uzyskać naprawdę fizyczny dlaczego; nie jestem pewien, czy zajmą one rzeczywistą przestrzeń, ale dostaje o wiele więcej miejsca complex).

 7
Author: ssube,
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-07-07 15:20:44