Elenco delle piattaforms supportate dallo standard C.

Qualcuno sa di qualsiasi piattaforma supportata dallo standard C, per la quale esiste ancora un lavoro di sviluppo attivo, ma che sono:

  • complemento non 2 o
  • la larghezza intera non è di 32 bit o 64 bit o
  • alcuni tipi interi hanno bit di riempimento o
  • se hai lavorato su un complemento a 2, il modello di bit con il bit di segno 1 e tutti i bit di valore zero non è un numero negativo valido o
  • la conversione di interi da firmata a non firmata (e viceversa) non avviene tramite la copia letterale di modelli di bit o
  • il giusto spostamento del numero intero non è uno spostamento aritmetico o
  • il numero di bit di valore in un tipo senza segno non è il numero di bit di valore nel tipo firmato corrispondente + 1 o
  • la conversione da un tipo int più ampio a un tipo più piccolo non avviene per troncamento dei bit più a sinistra che non si adatterebbero

EDIT: In alternativa, se ci sono piattaforms nel periodo 1995-1998 che hanno influenzato la decisione C99 di includere quanto sopra, ma che sono state interrotte, sarei interessato anche a loro.

EDIT: La motivazione generale ha questo da dire sui bit di riempimento:

I bit di riempimento sono accessibili all’utente in un tipo di intero senza segno. Ad esempio, supponiamo che una macchina utilizzi una coppia di cortocircuiti a 16 bit (ognuno con il proprio bit di segno) per creare un int a 32 bit e il bit di segno del cortocircuito inferiore viene ignorato quando viene utilizzato in questo int a 32 bit. Quindi, come int con 32 bit, c’è un bit di padding (nel mezzo dei 32 bit) che viene ignorato nel determinare il valore dell’int firmato a 32 bit. Ma, se questo articolo a 32 bit viene trattato come un int unsigned a 32 bit, quel bit padding è visibile al programma dell’utente. Alla commissione C è stato detto che esiste una macchina che funziona in questo modo, e questo è uno dei motivi per cui i bit di riempimento sono stati aggiunti a C99.

Le note a piè di pagina 44 e 45 indicano che i bit di parità potrebbero essere bit di riempimento. Il comitato non conosce alcuna macchina con bit di parità accessibili all’utente all’interno di un numero intero. Pertanto, il comitato non è a conoscenza di alcuna macchina che tratti i bit di parità come bit di riempimento.

Quindi un’altra domanda è, qual è quella macchina menzionata da C99?

EDIT: Sembra che il C99 stia considerando di rimuovere il supporto per il complemento 1 e la grandezza firmata: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n868.htm http: //www.open- std.org/jtc1/sc22/wg14/www/docs/n873.htm (cerca 6.2.6.2)

Recentemente ho lavorato in una società che utilizzava ancora una versione del PDP-10 e una porta di GCC su quella piattaforma. Il 10 che abbiamo usato aveva alcuni degli attributi che hai elencato:

  • Gli integer non hanno 32 o 64 bit e sono larghi 36 bit.
  • I bit di riempimento vengono utilizzati per alcune rappresentazioni. Per numeri interi a precisione estesa (ad esempio di tipo long long), la rappresentazione sottostante era 72 bit in cui ciascuna delle parole a 36 bit aveva un bit di segno.

Oltre agli attributi insoliti di cui sopra, c’era il problema che la macchina aveva diversi meccanismi di indirizzamento dei byte. I byte con ampiezze nell’intervallo di 6-12 bit di larghezza potrebbero essere indirizzati utilizzando bit speciali nell’indirizzo stesso che indicava quale larghezza e allineamento di parole era in uso. Per rappresentare un char * si potrebbe usare una rappresentazione che indirizzi i byte a 8 bit, i quali erano tutti allineati a sinistra nella parola, lasciando 4 bit in ogni parola a 36 bit che non erano affatto indirizzati. In alternativa, potrebbero essere usati byte da 9 bit che si adatterebbero uniformsmente alla parola a 36 bit. Entrambi questi approcci presentavano delle insidie ​​per la portabilità, ma al momento in cui me ne andai fu ritenuto più pratico usare i byte da 8 bit a causa dell’interazione con il networking TCP / IP e dispositivi standard che spesso pensano in termini di 16, 24 o 32 -bit campi che hanno anche una struttura di base di byte da 8 bit.

Per quanto ne so, questa piattaforma è ancora utilizzata nei prodotti sul campo, e in questa azienda c’è uno sviluppatore di compilatori che tiene aggiornate versioni relativamente recenti di GCC per consentire ulteriori sviluppi di C su questa piattaforma.

Va notato che non è ansible fare affidamento su comportamenti non definiti anche su piattaforms di uso comune, poiché i moderni compilatori di ottimizzazione eseguono trasformazioni di programma che mantengono solo un comportamento definito.

In particolare, non puoi contare sull’aritmetica del complemento a due che ti dà INT_MAX+1 == INT_MIN . Ad esempio, gcc 4.6.0 ottimizza quanto segue in un ciclo infinito:

 #include  int main() { int i = 0; while (i++ >= 0) puts("."); return 0; } 

EDIT : vedere qui per ulteriori informazioni sull’ottimizzazione firmata e le ottimizzazioni GCC.

Circa un decennio fa abbiamo dovuto trasferire il nostro database incorporato in C in un processore DSP che era il processore principale di uno stereo per auto. Era una macchina a 24 bit, nel peggiore dei modi: sizeof(char) == sizeof(int) == sizeof(void*) == 1 , che era 24 bit. Abbiamo chiamato il ramo che si occupava di questa porta “24-bit hell”.

Da allora abbiamo portato la nostra libreria su molte piattaforms, ma nessuna è stata così strana. Potrebbero essere ancora là fuori (i convenienti chip DSP a 24 bit sono ancora più economici ora), che si trovano in dispositivi a basso costo in cui la facilità di programmazione è lontana rispetto a una distinta base di materiali (BOM). Vieni a pensarci, penso che abbiamo incontrato una macchina in cui uno spostamento a destra di un intero senza segno non ha necessariamente inserito zero bit. Anche così, regole aritmetiche altamente non standard su una piattaforma garantiscono un porting di software impegnativo e sobject a errori, che aumenta drasticamente i costi di sviluppo del software. Ad un certo punto prevale la sanità mentale e si osservano gli standard.

Sospetto che molte delle motivazioni per la presenza di queste regole nel C99 siano la loro presenza in C89 e precedenti iterazioni della lingua. Non dimenticare che quando C è stato inventato, i computer erano molto più diversi rispetto a oggi. I progetti di processori “bit-slice” erano disponibili in cui è ansible aggiungere quanti chip si desidera al processore semplicemente aggiungendo i chip. E prima di C dovevi codificare in linguaggio assembly o preoccuparti esattamente di dove risiedesse il tuo codice, ecc.

C è stato un notevole passo avanti in termini di portabilità, ma ha dovuto compensare una vasta gamma di sistemi, quindi le regole molto generali. 20 anni dopo, quando Java è entrato in gioco, ha avuto il vantaggio della storia di permettergli di dichiarare in anticipo quanto sarebbero grandi i tipi primitivi, il che rende tutto molto più semplice, a patto che le scelte di Java siano valide.

So che stai principalmente chiedendo informazioni sui numeri interi, ma ho riscontrato alcune stranezze quando si tratta di indicatori. I primi computer Macintosh avevano processori a 32 bit (Motorola 68000), ma solo bus di memoria a 24 bit. Quindi 0x00123456 e 0xFF123456 si riferivano alla stessa cella di memoria, perché il processore tagliava gli 8 bit superiori quando si accede alla RAM. I tecnici Apple hanno usato questi bit per archiviare i metadati relativi alla memoria puntata dal puntatore. Pertanto, confrontando i puntatori, si è dovuto prima mascherare i bit superiori. E non farmi iniziare sulle architetture di memoria segmentate di x86. 🙂

Dato che siamo su questo argomento, date un’occhiata allo standard di codifica MISRA , che è favorito dai produttori di automobili che hanno bisogno di massima portabilità e sicurezza. Guarda anche Hacker’s Delight di Henry S. Warren, che contiene tantissimi utili trucchetti.

I miei due centesimi. Per favore non incolpare duramente, questo è dalla mia esperienza, non sono un teorico:

  • complemento non 2

Tutte le CPU esistenti sono il complemento a 2

  • la larghezza intera non è 32 bit o 64 bit

Ci sono anche architetture a 8 e 16 bit. MCU AVR a 8 bit è un buon esempio.

  • alcuni tipi interi hanno bit di riempimento

Non sono a conoscenza di alcun sistema, che integra interi. Numeri fluttuanti – è una storia diversa.

  • se hai lavorato su un complemento a 2, il modello di bit con il bit di segno 1 e tutti i bit di valore zero non è un numero negativo valido
  • la conversione di interi da firmata a non firmata (e viceversa) non avviene tramite la copia letterale di modelli di bit
  • il giusto spostamento del numero intero non è uno spostamento aritmetico
  • il numero di bit di valore in un tipo senza segno non è il numero di bit di valore nel tipo firmato corrispondente + 1
  • la conversione da un tipo int più ampio a un tipo più piccolo non avviene per troncamento dei bit più a sinistra che non si adatterebbero

Tutto quanto sopra – non ne sono a conoscenza e presumo che non ci sia una macchina del genere.

Anche se queste macchine sono antiche, c’è ancora una programmazione di comunità triggers per PDP-8, la maggior parte ma non tutte utilizzano simulazioni: PDP-8 come esempio . E questa macchina, AFAIK, usa numeri interi a 12 bit!

Sembra che il compilatore cc65 di Commodore C64 abbia avuto qualche aggiornamento fino a fine anno.

Un vecchio adagio (ho dimenticato l’attribuzione) lo dice

non esiste un codice portatile

Ma solo che ci sono dei codici che sono stati portati.

Non dovresti preoccuparti di scrivere codice portatile, dovresti preoccuparti di scrivere codice che sarà facile da trasferire su altre piattaforms.

Inoltre, usare solo lo standard C non ti dà molte cose utili. Gli standard Posix ti danno molto di più.