Ho tentato KR esercizio 2.1: determinare il range delle variabili long
mediante il calcolo diretto.Quando lo spostamento a sinistra non equivale a moltiplicare per 2
#include <stdio.h>
#include <limits.h>
int main()
{
unsigned short long_bits = sizeof(long) * CHAR_BIT;
printf("LONG_MAX = %ld\n", (1L << (long_bits - 1)) - 1);
printf("LONG_MIN = %ld\n", (-1) * (1L << (long_bits - 1)));
printf("ULONG_MAX (1) = %lu\n", (1UL << long_bits) - 1); // doesn't work
printf("ULONG_MAX (2) = %lu\n", 2*(1UL << (long_bits - 1)) - 1); // work
printf("\n");
}
ULONG_MAX (1) = 0
è sbagliato perché lo spostamento di overflow sinistra suppongo.ULONG_MAX (2) = 18446744073709551615
sembra corretto sostituendo l'ultimo spostamento sinistro con una moltiplicare per 2.
Così sembra che operatore di spostamento a sinistra soffre di troppo pieno, ma moltiplicazione non? Questo calcolo intermedio 2*(1UL << (long_bits - 1))
promuove in un tipo diverso da long
? Nella mia macchina, long
e long long
sono esattamente gli stessi (8 byte).
Edit: Come Lundin sottolineato, tutto il necessario per ULONG_MAX
è printf("ULONG_MAX = %lu\n", ~0L);
Uso spostamento a sinistra in questo caso causato UB, e moltiplicare per 2 è potenzialmente UB, troppo (anche se risultato di cassa 2 look corretta).
Come regola generale: l'aritmetica firmata soffre di (potenziale) overflow; aritmetica senza segno * non può * overflow (poiché eseguito modulo 2^N). – Jens
Il caso 2 non è corretto neanche ... a causa di overflow come nel caso 1 – LPs
@LPs - l'output del caso 2 sembra corretto. Questa è la mia domanda, l'overflow non sembra accadere in questo caso – artm