Eu sei que os padrões C e C ++ deixam muitos aspectos da implementação de linguagem definidos apenas porque, se houver uma arquitetura com outras características, seria muito difícil ou impossível escrever um compilador em conformidade com ele.
Eu sei que 40 anos atrás, qualquer computador tinha sua própria especificação. No entanto, não conheço nenhuma arquitetura usada hoje em que:
CHAR_BIT != 8
signed
não é o complemento de dois (ouvi dizer que Java teve problemas com este).- O ponto flutuante não é compatível com IEEE 754 (Editar: eu quis dizer "não está na codificação binária IEEE 754").
A razão pela qual estou perguntando é que muitas vezes explico às pessoas que é bom que o C ++ não exija outros aspectos de baixo nível, como tipos de tamanho fixo † . É bom porque, diferentemente de outras línguas, torna seu código portátil quando usado corretamente (Edit: porque ele pode ser portado para mais arquiteturas sem exigir a emulação de aspectos de baixo nível da máquina, como por exemplo, aritmética de complemento de dois na arquitetura sign + magnitude) . Mas me sinto mal por não poder apontar para nenhuma arquitetura específica.
Portanto, a pergunta é: quais arquiteturas exibem as propriedades acima?
† uint*_t
s são opcionais.
fonte
Respostas:
Dê uma olhada neste
Servidores Unisys ClearPath Dorado
oferecendo compatibilidade com versões anteriores para pessoas que ainda não migraram todos os seus softwares Univac.
Pontos chave:
CHAR_BIT == 9
Não sei se eles oferecem um compilador C ++, mas poderiam .
E agora surgiu um link para uma edição recente do manual C:
Manual de referência de programação do compilador Unisys C
A Seção 4.5 possui uma tabela de tipos de dados com 9, 18, 36 e 72 bits.
fonte
char*
evoid*
deve ser do mesmo tamanho, e grande o suficiente para segurar qualquer outro ponteiro. O resto depende da implementação.sizeof(int*) == 2
, os ponteiros distantes também tinham um seletor de 16 bitssizeof(void*) == 4
.sizeof(int*) != sizeof(char*)
aqui: ambos são 36 bits. Mas o seletor de bytes nochar*
está nos bits de ordem superior e é ignoradoint*
. (Eu usei outras máquinas, no entanto, em que `sizeof (char *)> sizeof (int *)).void*
) sempre tiveram o mesmo tamanho. (Claro, você não pode converter um ponteiro de função paravoid*
, uma vez quevoid*
pode ser menor, mas de acordo com o padrão, você não pode fazer isso hoje, qualquer um..)Nenhuma de suas suposições vale para mainframes. Para iniciantes, não conheço um mainframe que use o IEEE 754: a IBM usa o ponto flutuante da base 16 e os dois mainframes da Unisys usam a base 8. As máquinas Unisys são um pouco especiais em muitos outros aspectos: Bo mencionou o 2200 arquitetura, mas a arquitetura MPS é ainda mais estranha: palavras marcadas com 48 bits. (Se a palavra é um ponteiro ou não, depende de um pouco na palavra.) E as representações numéricas são projetadas para que não haja distinção real entre ponto flutuante e aritmética integral: o ponto flutuante é a base 8; ele não requer normalização e, ao contrário de todos os outros pontos flutuantes que eu vi, coloca o decimal à direita da mantissa, em vez da esquerda, e usa magnitude assinada para o expoente (além da mantissa). Com os resultados que um valor integral de ponto flutuante possui (ou pode ter) exatamente a mesma representação de bits que um número inteiro de magnitude assinado. E não há instruções aritméticas de ponto flutuante: se os expoentes dos dois valores são ambos 0, a instrução faz aritmética integral, caso contrário, faz aritmética de ponto flutuante. (Uma continuação da filosofia de marcação na arquitetura.) O que significa que, embora
int
pode ocupar 48 bits, 8 deles devem ser 0 ou o valor não será tratado como um número inteiro.fonte
A conformidade total com o IEEE 754 é rara em implementações de ponto flutuante. E enfraquecer a especificação a esse respeito permite muitas otimizações.
Por exemplo, o suporte subnorm difere entre x87 e SSE.
Otimizações como a fusão de uma multiplicação e adição que foram separadas no código-fonte também alteram levemente os resultados, mas é uma ótima otimização em algumas arquiteturas.
Ou no x86, a conformidade estrita com a IEEE pode exigir a definição de determinados sinalizadores ou transferências adicionais entre registradores de ponto flutuante e memória normal para forçá-lo a usar o tipo de ponto flutuante especificado em vez de flutuações internas de 80 bits.
E algumas plataformas não possuem flutuadores de hardware e, portanto, precisam imitá-las no software. E alguns dos requisitos do IEEE 754 podem ser caros de implementar em software. Em particular, as regras de arredondamento podem ser um problema.
Minha conclusão é que você não precisa de arquiteturas exóticas para entrar em situações em que nem sempre deseja garantir uma conformidade estrita com o IEEE. Por esse motivo, poucas linguagens de programação garantem conformidade estrita com o IEEE.
fonte
long double
poderiam ter sido do tipo útil e duradouro, já que o único problema real era que ele trabalha malprintf
. O fato de que o duplo estendido armazena o líder 1 acelera explicitamente os cálculos em sistemas que não são da FPU e também elimina a necessidade de tratamento especial de denormals em qualquer contexto que não seja a conversão de / para outros tipos. Pena que o Cprintf
estragou tudo.Eu encontrei este link listando alguns sistemas onde
CHAR_BIT != 8
. Eles incluemE, claro, há uma pergunta sobre o Stack Overflow: Quais plataformas têm algo diferente de char de 8 bits
Quanto aos sistemas sem complemento de dois, há uma leitura interessante sobre o comp.lang.c ++. Moderado . Resumido: existem plataformas que possuem complemento ou sinal e representação de magnitude.
fonte
CHAR_BIT=32
e o Texas Instruments DSP do TMS32F28xx possuiCHAR_BIT=16
. O GCC 3.2 para PDP-10 possuiCHAR_BIT=9
. Eu acho que o S / 360 também pode ter um char não de 8 bits.CHAR_BITS
é uma duplicata parcial.Tenho certeza de que os sistemas VAX ainda estão em uso. Eles não suportam ponto flutuante IEEE; eles usam seus próprios formatos. O Alpha suporta os formatos de ponto flutuante VAX e IEEE.
Máquinas de vetores Cray, como o T90, também têm seu próprio formato de ponto flutuante, embora os sistemas Cray mais novos usem IEEE. (O T90 que eu usei foi desativado há alguns anos; não sei se ainda há algum em uso ativo.)
O T90 também tinha / tem algumas representações interessantes para ponteiros e números inteiros. Um endereço nativo pode apontar apenas para uma palavra de 64 bits. Os compiladores C e C ++ tinham CHAR_BIT == 8 (necessário porque ele executava o Unicos, uma versão do Unix, e precisava interoperar com outros sistemas), mas um endereço nativo só poderia apontar para uma palavra de 64 bits. Todas as operações no nível de bytes foram sintetizadas pelo compilador e a
void*
ouchar*
armazenou um deslocamento de bytes nos 3 bits de ordem superior da palavra. E acho que alguns tipos inteiros tinham bits de preenchimento.Os mainframes da IBM são outro exemplo.
Por outro lado, esses sistemas específicos não precisam necessariamente impedir alterações no padrão de linguagem. Cray não mostrou nenhum interesse particular em atualizar seu compilador C para C99; presumivelmente a mesma coisa aplicada ao compilador C ++. ele pode ser razoável para apertar os requisitos para implementações hospedadas, como a exigência CHAR_BIT == 8, formato IEEE de ponto flutuante se não a semântica completa, e 2 'S-complemento sem padding bits para inteiros assinados. Os sistemas antigos poderiam continuar a oferecer suporte aos padrões anteriores de linguagem (o C90 não morreu quando o C99 foi lançado) e os requisitos podem ser mais flexíveis para implementações independentes (sistemas embarcados), como DSPs.
Por outro lado, pode haver boas razões para sistemas futuros fazerem coisas que seriam consideradas exóticas hoje.
fonte
unsigned
tipos integrais serão uma grande dor, enquanto que a aritmética assinada ficará bem.CHAR_BITS
De acordo com o código fonte do gcc :
CHAR_BIT
é16
bits para 1750a , dsp16xx arquiteturas.CHAR_BIT
é24
bits para a arquitetura dsp56k .CHAR_BIT
é32
bits para a arquitetura c4x .Você pode encontrar mais facilmente fazendo:
ou
se
CHAR_TYPE_SIZE
estiver definido adequadamente.Conformidade com IEEE 754
Se a arquitetura de destino não suportar instruções de ponto flutuante, o gcc poderá gerar fallback de software, que por padrão não é compatível com o padrão.
-funsafe-math-optimizations
Além disso , opções especiais (como a bruxa também desativa a preservação de zeros) podem ser usadas.fonte
A representação binária IEEE 754 era incomum em GPUs até recentemente, consulte Paranoia de ponto flutuante da GPU .
EDIT: uma questão foi levantada nos comentários se o ponto flutuante da GPU é relevante para a programação de computador usual, não relacionada aos gráficos. Claro que sim! A maior parte do desempenho industrial atualmente calculado é feito em GPUs; a lista inclui IA, mineração de dados, redes neurais, simulações físicas, previsão do tempo e muito mais. Um dos links nos comentários mostra o motivo: uma vantagem de ponto flutuante de ordem de magnitude das GPUs.
Outra coisa que eu gostaria de acrescentar, que é mais relevante para a questão do OP: o que as pessoas fizeram 10 a 15 anos atrás quando o ponto flutuante da GPU não era o IEEE e quando não havia API como o OpenCL ou CUDA de hoje para programar GPUs? Acredite ou não, os pioneiros da computação em GPU conseguiram programar GPUs sem uma API para fazer isso ! Eu conheci um deles na minha empresa. Aqui está o que ele fez: ele codificou os dados que precisava para calcular como uma imagem com pixels representando os valores em que estava trabalhando, depois usou o OpenGL para executar as operações necessárias (como "desfoque gaussiano" para representar uma convolução com uma distribuição normal) , etc) e decodificou a imagem resultante novamente em uma matriz de resultados. E isso ainda era mais rápido do que usar CPU!
Coisas assim foram o que levou a NVidia a finalmente tornar seus dados internos binários compatíveis com o IEEE e a introduzir uma API orientada à computação, e não à manipulação de imagens.
fonte
int f(int n) { return n <= 1 ? 1 : n * f(n-1); }
no CUDA? Se não, as GPUs não são relevantes para esta pergunta (que pergunta sobre os comitês C e C ++).