Sexta-feira, Agosto 21, 2009

Tipos de dados primitivos 2

Em C++, existe uma certa ambiguidade no significado dos tipos primitivos.

Tome char, por exemplo. char pode ser apenas char, pode ser signed char ou pode ser unsigned char. Mas char deve ser caractere, certo? Qual é o significado de um caractere ser signed ou unsigned? Nenhuma.

Existe, é claro, uma razão porque é possível especificar unsigned ou signed char; porque char é um valor inteiro de tamanho 1. De certa forma, char é o menor de todos os int, e foi projetado para ser usado como tal. Em uma máquina convencional, char é um inteiro de 8 bits. C99 na prática exige que char ocupe 8 bits.

Em C original, o ponteiro para char possuía a propriedade adicional de representar qualquer endereço válido de memória. Portanto, uma função que lê dados de um dispositivo qualquer para a memória aceitaria um parâmetro do tipo ponteiro para char significando o endereço de memória de um buffer.

É claro que isso provoca uma confusão com outro sigficado de ponteiro para char, a string de bytes terminada por NULL, ou NTBS. Por esse motivo, alguns programas e bibliotecas usam ponteiro para unsigned char para representar segmentos opacos de memória, como buffers de I/O.

Em C99, qualquer ponteiro é conversível para um ponteiro para algum char. Em C++ isso não é permitido. Em ambas as linguagens, qualquer ponteiro é conversível para um ponteiro para void.

Aritmética de ponteiro não é permitia para um ponteiro para void, infelizmente; programas que desejam atravessar a memória por qualquer razão devem usar ponteiros para char. Isso exige o uso de conversões por reinterpretação, como a notação de cast com parênteses, ou reinterpret_cast.

Existem aqui diversas necessidades diferentes. Uma delas é endereçar memória opaca, sem interpretação, e endereçá-la completamente. Outra é representar o menor valor inteiro possível na plataforma. Outra é representar um caractere. Outra é representar um segmento de texto.

Representar um caractere como o menor inteiro da plataforma é, hoje sabemos, uma ingenuidade, e existem diversas representações de caracteres que usam um número variado dessas unidades para caracteres, ou usam um número fixo de duas ou mais dessas unidades.

Assim, quando ocorre em um programa um caractere literalmente, como f, qual é a quantidade de armazenagem que o valor correspondente ocupa na memória? Depende da representação de caracteres usada no sistema alvo -- e naturalmente na unidade de memória da arquitetura alvo.

Eu não gosto dessa notação de signed e unsigned. Parece ter havido um problema original em que os ints tiveram de ser subitamente diferenciados entre inteiros e inteiros positivos. Não entendo como isso pode ter sido súbito, mas ainda não conheço bem a história da computação para saber como eram as máquinas quando C foi projetada. Me parece apenas que é um sistema de tipos obsoleto. As máquinas conhecem os naturais, ou inteiros positivos, representados em base 2 e conhece os inteiros representados em base 2 com complemento de dois.

Caracteres são um outro tipo de informação, distinto de números, apesar de logicamente relacionáveis -- a representação de um caractere é um índice em uma tabela.

0 comentários: