2015-09-22 17 views
5

sto attraversando un po 'vecchio codice C utilizzando Lint che inciampato su questa linea:Qualche motivo per assegnare -0?

int16_t max = -0; 

Il messaggio Lint è che la "espressione costante restituisce 0 in funzione '-'".

C'è qualche motivo per cui qualcuno dovrebbe usare -0?

+5

Se l'architettura di destinazione ha '0' negativo per' int' – Olaf

+7

Forse è una tilde '~' non un meno '-'? –

+0

@Olaf: quali architetture avevano questo e perché era utile? –

risposta

4

No, non vedo alcun motivo per questo. Altri hanno detto che è possibile avere piattaforme con "zero negativo", ma tale zero negativo non può mai essere prodotto da questa espressione, quindi questo è inutile.

Il paragrafo corrispondente nello standard C è 6.2.6.2 p3, corsivo è mio:

Se l'implementazione supporta zeri negativi, essi devono essere generati solo da :

- il &, |, ^, ~, < <, e >> operatori con operandi che producono un tale valore;

- gli operatori +, -, *, /, e% in cui un operando è uno zero negativo e il risultato è zero;

- composto operatori di assegnazione in base ai casi precedenti.

Per produrre uno zero negativo su tale piattaforma si potrebbe usare ~INT_MAX, per esempio, ma che non sarebbe uno zero per altre rappresentazioni, in modo che il codice non sarebbe molto portabile.

+1

Hmmm: 6.2.6.2 sembra addirittura precludere 'long mz = strtol (" - 0 ", NULL, 10)' dalla creazione di '-0' anche quando l'implementazione supporta zero negativi. – chux

+1

@chux, si la penso così. L'idea è che lo zero negativo dovrebbe essere evitato dall'architettura dove possono. Dovrebbero essere prodotti solo da manipolazioni bit, dove sono inevitabili. –

+1

Sono d'accordo con il reclamo, ma il programmatore potrebbe aver pensato diversamente o ha usato un compilatore non standard. Si tratta di un dispositivo incorporato e di un vecchio codice, quindi è molto probabile che il compilatore abbia alcune estensioni/modifiche (abbastanza comuni alcuni anni fa). – Olaf

7

Nella specifica C (6.2.6.2 tipi interi), esso indica quanto segue (sottolineatura mia):

Per tipi interi con segno, i bit della rappresentazione dell'oggetto sono suddivisi in tre gruppi : bit di valore, bit di riempimento e bit di segno. Non è necessario alcun bit di riempimento; ci deve essere esattamente un bit di segno. Ogni bit che è un bit di valore deve avere lo stesso valore dello stesso bit nella rappresentazione dell'oggetto del corrispondente tipo senza segno (se ci sono bit di valore nel tipo firmato e N nel tipo senza segno, quindi M £ N). Se il bit di segno è zero, non deve influire sul valore risultante. Se il bit di segno è uno, il valore deve essere modificato in uno dei seguenti modi:

  • il valore corrispondente con il bit di segno 0 viene negato (segno e grandezza);
  • il bit di segno ha il valore - (2N) (complemento a due);
  • il bit di segno ha il valore - (2N - 1) (complemento).

Quale di queste applica è definito dall'implementazione, come se il valore con bit di segno 1 e tutti i bit zero (per i primi due), o con bit di segno e tutti i bit di valore 1 (per il proprio complemento), è una rappresentazione della trappola o un valore normale. In caso di segno e grandezza e complemento a uno, se questa rappresentazione è un valore normale è chiamato zero zero.

In altre parole, C supporta tre diversi representations for signed integers e due di loro hanno il concetto di signed zero, che distingue tra un positivo e uno zero negativo.

Quindi, la mia spiegazione è che forse l'autore dello snippet di codice stava cercando di produrre un valore zero negativo. Ma, come sottolineato in Jens Gustedt's answer, questa espressione non può effettivamente produrre uno zero negativo, il che significa che l'autore potrebbe aver fatto un'assunzione sbagliata lì.

0

Vale per un'architettura che utilizza una CPU con numeri one's complement.

  • Un complemento di un è un modo per rappresentare numeri negativi, con un -0. Ancora in uso per virgola mobile.
  • Per i numeri non firmati il ​​numero massimo è infatti -0: tutti 1s.

Siamo abituati ai numeri di complemento a due, con un numero negativo in più. Sebbene il complemento di uno abbia dei problemi intorno allo zero, lo stesso vale per il complemento a due attorno a MIN_INT: -MIN_INT == MIN_INT.

Nel codice di cui sopra, probabilmente destinati stata numeri senza segno:

uint16_t max = (uint16_t) -1; 
+0

Potrebbe anche essere segno/grandezza. – Olaf

+0

@Olaf yes, anche se il massimo 100000 sarebbe il numero dopo il massimo firmato int, in qualche modo non utile. –

+0

Hmm .. è quel binario'100000'? Perché dovrebbe essere il "numero dopo' INT_MAX'? È un valore negativo '0', come per il complemento a 1. – Olaf

0

Non c'è ragione per questo con C99 o successivo.

int16_t è un tipo intero con larghezza esatta.

Il nome typedef intN_t indica un tipo intero con segno con larghezza N, senza bit di riempimento, ed una rappresentazione complemento a due. Pertanto, int8_t indica un tipo di intero con segno con una larghezza di esattamente 8 bit. C11dr §7.20.1.1 1

Non c'è zero firmato con complemento a due. Quindi il codice è equivalente al

int16_t max = 0; 

IMO, la int16_t max = -0;sperato per conseguenza, sulla piattaforma complemento un non-2, era inizializzare max a -0 a bandiera un array di lunghezza 0 o uno che solo elementi contenuti con il valore -0.