2013-08-07 6 views
9

In sezione 7.18.1.1 paragrafo 1 dello standard C99:Una conversazione int16_t in int genera un comportamento definito dall'implementazione?

Il nome typedef intN_t indica un tipo intero con segno Larghezza N, senza imbottitura bit, e la rappresentazione complemento a due.

Secondo lo standard C99, esatto larghezza firmato tipi interi sono tenuti ad avere complemento rappresentazione di un due. Ciò significa che, ad esempio, int8_t ha un valore minimo di -128 rispetto al valore del complemento del valore minimo di -127.

Sezione 6.2.6.2 paragrafo 2 permette l'implementazione di decidere se interpretare un po 'segno come segno e la grandezza, complemento a due, o complemento a uno:

Se il segno bit è uno, il valore deve essere modificato in uno dei seguenti modi:
- il valore corrispondente con il bit di segno 0 è negato (segno e grandezza);
- il bit di segno ha il valore - (2 N) (complemento a due);
- il bit di segno ha il valore - (2 N - 1) (un complemento).

Il distinto tra i metodi è importante perché il valore minimo di un numero intero complemento a due (-128) può essere al di fuori dell'intervallo di valori rappresentabili in complemento quelli (-127 a 127).

Supponiamo un'implementazione definisce i tipi int come aventi ones' complement rappresentazione, mentre il tipo int16_t ha two's complement rappresentazione come garantito dallo standard C99.

int16_t foo = -32768; 
int bar = foo; 

In questo caso, sarebbe la conversione da int16_t a causa intimplementazione definita comportamento poiché il valore contenuto foo non rientra nell'intervallo di valori rappresentabili con bar?

+0

È molto improbabile che un'implementazione abbia 'int16_t' e' int' con una rappresentazione firmata complementare. È la base logica per C per contrassegnare questi tipi interi di larghezza esatta come facoltativi. – ouah

+0

Mi chiedo perché i tipi interi con segno di larghezza esatta abbiano questo requisito esplicito del * complemento * di * piuttosto che lasciarlo all'implementazione come fanno i tipi interi con segno di base. –

risposta

7

Sì.

In particolare, la conversione produrrebbe un risultato definito dall'implementazione. (Per qualsiasi valore diverso da -32768, il risultato e il comportamento sarebbero ben definiti.) Oppure la conversione potrebbe generare un segnale definito dall'implementazione, ma non conosco alcuna implementazione che lo faccia.

Domanda di regole di conversione: N1570 6.3.1.3p3:

Altrimenti, il nuovo tipo è firmato e il valore non può essere rappresentato in esso; il risultato è definito dall'implementazione oppure viene generato un segnale definito dall'implementazione .

Questo può avvenire solo se:

  • int è 16 bit (più precisamente, ha 15 bit di valore, 1 bit di segno, e 0 o più bit di riempimento)
  • int usa le one's- complementare oppure registrati e la grandezza
  • L'implementazione supporta anche in complemento a due (altrimenti semplicemente non definirà int16_t).

Sarei sorpreso di vedere un'implementazione che soddisfi questi criteri. Dovrebbe supportare sia il complemento a due sia il complemento o il segno e la magnitudine, e dovrebbe scegliere uno di questi ultimi per il tipo int. (Forse un'implementazione non a due complementi potrebbe supportare il complemento a due nel software, solo per poter definire int16_t.)

Se sei preoccupato per questa possibilità, potresti considerare di aggiungere questo a uno di i file di intestazione:

#include <limits.h> 
#include <stdint.h> 

#if !defined(INT16_MIN) 
#error "int16_t is not defined" 
#elif INT_MIN > INT16_MIN 
#error "Sorry, I just can't cope with this weird implementation" 
#endif 

Le #error s non sono suscettibili di scatenare su qualsiasi implementazione nel mondo reale sano di mente.

+1

Inoltre, poiché l'implementazione di 'int16_t' è facoltativa, dovresti anche verificare se' INT16_MIN' è definito. – jxh

+0

@jxh Lo standard C99 richiede che 'INT16_MIN' sia definito se' int16_t' è anche definito? –

+1

Da C.99 §7.18 ¶4: Per ogni tipo qui descritto che l'attuazione prevede, '' è dichiarare che 'typedef' nome e definire le macro associate. Al contrario, per ogni tipo qui descritto che l'implementazione non fornisce, '' non deve dichiarare che 'typedef' nome ** né deve definire le macro associate. ** – jxh

Problemi correlati