2016-02-01 43 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; 
} 

L'uscita di questo codice sia in C e C++, su cygwin64 e una macchina rhel6.4 con gcc 5.2.0 è:comprensione 2^31 e -2^31 intero promozione

sizeof(int): 4 
1 
0 
1 
0 

Secondo "Integer promotions", 2147483648u sarà di tipo unsigned int (anche senza il suffisso u) e -2147483648 di tipo int (come al solito). Perché i diversi risultati con il casting esplicito?

Secondo il "Usual arithmetic conversions", questo paragrafo vale:

Altrimenti, il signedness è diverso: Se l'operando con il tipo senza segno ha una maggiore conversione rango o uguale al rango di tipo di l'operando firmato, quindi l'operando con il tipo firmato è implicitamente convertito nel tipo unsigned

Ciò significa che il risultato corretto è come se:

2147483648u > 2147483648u 
2147483648u != 2147483648u 

sono stati eseguiti, perché in 32 bit, firmato -2^31 e senza segno 2^31 hanno la stessa rappresentazione. In altre parole, il risultato con il cast è corretto. Cosa sta succedendo?

Ho la sensazione che in qualche modo, una promozione intera di rango più elevato venga applicata senza eseguire il casting, quindi ricevo ad es. una promozione firmata a 64 bit su entrambi i lati - ma perché?

Entrambi gli eseguibili sono compilati come 64 bit, può questo svolgere un ruolo?

+0

Si prega di scegliere uno dei C e C++. Queste due lingue sono diverse e la risposta potrebbe essere diversa per entrambi. – fuz

+2

@FUZxxl: non è, in questo caso. – DevSolar

+0

Inoltre, su quale standard C stai compilando? Gestione delle costanti integer modificate in C11. – fuz

risposta

12

Non ci sono costanti integer negative. Ci sono solo quelli positivi con l'operatore unario - applicato.

Da 2147483648 > INT_MAX, che promuove 2147483648 alla prossima grande sottoscritto (perché non hai accodare u) tipo intero, prima di il - viene applicato.


Tra l'altro, è per questo che INT_MIN viene solitamente definita come (-INT_MAX - 1) in <limits.h>. ;-)

+1

Wow, questo non mi ha mai colpito in circa 17 anni di codifica in c/C++ :-) – Irfy

+0

In * mio * caso, sono fortunato e questo è il caso. Comunque win64 ha una lunghezza di 4 byte, quindi se lo avessi fatto con un compilatore VC, non sarebbe stato il caso. – Irfy

+0

Se stai provando a raggiungere un limite, prova a inserire -2^63 e -2^127 (calcolato) come letterale :) – Irfy