2016-02-01 13 views
5
#include <stdio.h> 

int main() { 
    printf("sizeof(int): %zu\n", sizeof(int)); 
    printf("%d\n", 2147483648u > -2147483648); 
    printf("%d\n", ((unsigned int)2147483648u) > ((int)-2147483648)); 
    printf("%d\n", 2147483648u != -2147483648); 
    printf("%d\n", ((unsigned int)2147483648u) != ((int)-2147483648)); 
    return 0; 
} 

Wyjście tego kodu zarówno C i C++, w cygwin64 i urządzenie rhel6.4 z gcc 5.2.0 jest:Zrozumienie 2^31^31 i -2 całkowitą promowanie

sizeof(int): 4 
1 
0 
1 
0 

Zgodnie z "Integer promotions", 2147483648u będzie typu unsigned int (nawet bez sufiksu u) i -2147483648 typu int (jak zwykle). Dlaczego różne wyniki z wyraźnym castingiem?

Według „Usual arithmetic conversions”, ustęp ten ma zastosowanie:

Inaczej, uzyskiwany znak jest inny: Jeśli operand z typu unsigned ma większą rangę konwersji lub równa randze rodzaj podpisany argumentu, a operand z zawartą typu niejawnie przeprowadzono w unsigned

oznacza to, że prawidłowy wynik jest, gdy:

2147483648u > 2147483648u 
2147483648u != 2147483648u 

zostały wykonane, ponieważ w 32 bitach, podpisane -2^31 i bez znaku 2^31 mają tę samą reprezentację. Innymi słowy, wynik rzucania jest poprawny. Co się dzieje?

Mam wrażenie, że w jakiś sposób promocja liczb całkowitych o wyższej randze jest stosowana bez przesyłania, więc otrzymuję np. 64-bitowa podpisana promocja po obu stronach - ale dlaczego?

Oba pliki wykonywalne są skompilowane jako 64-bitowe, czy może to odgrywać rolę?

+0

Proszę wybrać jedną z C i C++. Te dwa języki są różne i odpowiedź może być inna dla obu. – fuz

+2

@FUZxxl: W tym przypadku nie jest. – DevSolar

+0

Poza tym, z którym typem C kompilujesz? Obsługa stałych całkowitych została zmieniona w C11. – fuz

Odpowiedz

12

Nie ma ujemnych stałych całkowitych. Są tylko pozytywne z zastosowaniem unarnego operatora -.

Od 2147483648 > INT_MAX, który promuje 2147483648 do następnego większy podpisany (bo nie dołączy u) typu INTEGER, przed- jest stosowana.


Nawiasem mówiąc, dlatego INT_MIN definiuje się zwykle jako (-INT_MAX - 1) w <limits.h>. ;-)

+1

Wow, to nigdy nie uderzyło mnie w około 17 lat kodowania w c/C++ :-) – Irfy

+0

W * moim * przypadku, mam szczęście i tak właśnie jest. Jednak win64's long to 4 bajty, więc jeśli miałbym to zrobić z kompilatorem VC, to nie byłoby tak. – Irfy

+0

Jeśli próbujesz osiągnąć limit, spróbuj wprowadzić -2^63 i -2^127 (wyliczone) jako literał :) – Irfy

Powiązane problemy