2017-04-24 33 views
5

Mam wątpliwości z poniższych 2 fragmentów kodu.Przepełnienie danych przy porównywaniu wartości

Uruchomiłem ten kod na maszynie 64-bitowej (x86_64-linux-gnu). Widzę przepełnienie wartości Val, gdy typem danych jest unsigned integer.

#include<stdio.h> 
main() 
{ 
    unsigned int Val = 0xFFFFFFFF-15, Val2 = 0xFFFFFFFF; 
    if (Val+16 < Val2) 
    { 
     printf("Val is less than Val2\n"); 
    } 
} 

Jeśli typ danych to unsigned char, to nie powoduje przepełnienia.

#include<stdio.h> 
main() 
{ 
    unsigned char Val = 0xFF-15, Val2 = 0xFF; 
    if (Val+16 < Val2) 
    { 
     printf("Val is less than Val2\n"); 
    } 
} 

Mam dwa pytania:

  1. Czy wartość Val awansować na wysokie typu danych, gdy typ danych jest unsigned char?
  2. Jeśli tak, dlaczego nie został awansowany z 32-bitowego na 64-bitowy unsigned long?
+8

To nie są lata 90-te - obecnie wymagany jest typ zwracania na 'main'. – InternetAussie

+0

Gdy arytmetyka, wszystko jest promowane do "int", jeśli można dopasować, lub do "unsigned int", jeśli nie może. Rozmiar tych typów jest specyficzny dla kompilatora i można go łatwo znaleźć. –

Odpowiedz

6

Standard C11 mówi następujące (C11 6.3.11p2.2):

Jeśli int może reprezentować wszystkie wartości tego samego typu (jak ograniczona przez szerokość, dla bit-field), wartość jest konwertowana na int; w przeciwnym razie zostanie przekonwertowany na unsigned int. Są to tak zwane promocje bezpośrednie. Wszystkie inne typy są niezmienione przez promocje całkowite.

Zatem:

  1. unsigned char będzie promowana - jednak jest to szczegół realizacja czy int może reprezentować wszystkie wartości unsigned char - więc to może być promowany do unsigned int na tych platformach. Twoja nie jest jedną z tych platform, więc twoje drugie porównanie to (int)Val + 16 < (int)Val2.

  2. , jak mówi ostatnie zdanie cytowanego paragrafu, to nigdy nie jest promowane. Ponieważ arytmetyka jest wykonywana na unsigned ints w pierwszym fragmencie, wynik 0xFFFFFFFF - 15 + 16 jest 0U na komputerze z 32-bitową wartością unsigned int.

2

Tak, w drugim przypadku numery są promowane na int. Po zmodyfikowaniu kodu:

#include<stdio.h> 
int main() 
{ 
    unsigned char Val = 0xFF-15, Val2 = 0xFF; 
    if ((unsigned char)(Val+16) < Val2) 
    { 
     printf("Val is less than Val2\n"); 
    } 
} 

Otrzymasz zachowanie, którego się spodziewasz.

+0

Dziękuję wszystkim. Teraz jest to bardzo jasne. –