A maioria dos desenvolvedores de aplicativos usa números inteiros assinados em locais onde eles realmente pretendem usar números inteiros não assinados? Eu faço isso o tempo todo, assim como meus colegas de trabalho. Não vi muitas outras bases de código extensas (além da Delphi VCL) e exemplos na internet geralmente usam números inteiros. Enquanto os desenvolvedores da VCL usam seus próprios tipos de dados (que seria a maneira mais preguiçosa de declarar variáveis).
Algo parece um pouco terrível sobre código como este
TStuffRec = record
recordID : Integer;
thingID : Integer;
otherThingID : Integer;
end;
quando poderia ser escrito como
TStuffRec = record
recordID : Cardinal;
thingID : Cardinal;
otherThingID : Cardinal;
end;
Funcionalmente, esses registros quase sempre funcionam da mesma maneira (e esperamos que continuem funcionando da mesma forma, mesmo no Delphi de 64 bits). Mas números muito grandes terão problemas de conversão.
Mas também há desvantagens no uso de entradas não assinadas. Principalmente devido ao quão irritante é misturar os dois.
A verdadeira questão é: isso é algo que realmente é pensado ou incluído nas melhores práticas? Geralmente depende apenas do desenvolvedor?
fonte
Respostas:
Uma razão pela qual eu não uso tanto tipos inteiros não assinados no Delphi é que eles podem criar problemas quando misturados com números inteiros assinados. Aqui está um que me mordeu uma vez:
Eu tinha
i
declarado como um número inteiro sem sinal (afinal, é um índice em uma lista que começa em 0, nunca precisa ser negativa, certo?), Mas quandoList.Count
era 0, não iria causar um curto-circuito no loop conforme o esperado, porque0 - 1
avalia para um número positivo realmente alto. Opa!Entre os possíveis problemas de segurança inerentes à mistura de números inteiros assinados e não assinados e os problemas de intervalo (se você precisar de números positivos maiores que
high(signed whatever)
, é bem provável que você também acabe precisando de números positivos maioreshigh(unsigned whatever)
também) até o próximo tamanho maior, em vez de mudar de assinado para não assinado do mesmo tamanho, geralmente é a ação correta.) Realmente não encontrei muitos usos para números inteiros não assinados ao representar a maioria dos dados.fonte
Para ser sincero, costumo usar números inteiros por hábito. Eu me acostumei ao fato de que eles oferecem intervalos grandes o suficiente para a maioria das situações e permitem valores negativos (como -1). De fato, muitas vezes o uso de bytes / palavra / abreviação seria mais apropriado. Agora, pensando nisso, posso me concentrar nesses pontos:
Perspectiva. O tamanho do mapa de bloco é limitado a blocos de 192x192, portanto, eu poderia usar o byte para endereçar blocos e loops. Mas se o tamanho do mapa aumentar, terei que passar por todos os usos e substituí-lo por, por exemplo, word. Quando eu preciso permitir objetos fora do mapa, tenho que ir novamente para mudar para smallint.
Rotações. Geralmente, escrevo um loop "de i: = 0 a Count-1", o que acontece se "i" for byte e Count = 0 é que o loop é executado de 0 a 255. Não que eu o desejasse.
Uniformização. É mais fácil lembrar e aplicar "var i: integer;" do que parar em cada caso e pensar "Hm .. aqui estamos lidando com o intervalo 0..120 .. byte .. não, espere, talvez precisemos de -1 para não inicializado .. abreviado .. espere .. e se 128 for não é suficiente .. Arrgh! " ou "Por que é pequeno neste local, não é pequeno?"
Combinando. Quando preciso combinar duas ou mais classes, elas podem estar usando tipos de dados diferentes para seus propósitos, o uso de tipos mais amplos permite ignorar conversões desnecessárias.
-1. Mesmo quando os valores estão no intervalo 0..n-1, muitas vezes preciso definir o valor "sem valor / desconhecido / não inicializado / vazio", que é, na prática comum -1.
O uso de números inteiros permite ignorar todos esses problemas, esquecer a otimização de baixo nível onde não é necessário, aumentar o nível e se concentrar em problemas mais reais.
PS Quando uso outros tipos?
fonte
A melhor prática é usar um tipo de dados que atenda às necessidades dos dados que estão sendo usados (dados esperados).
Exemplos de C #: se eu precisasse suportar apenas 0 a 255, usaria um byte.
Se eu precisasse apoiar 1.000.000 negativos e positivos, então int.
Maior que 4,2 bilhões, use um longo.
Ao escolher o tipo correto, o programa usará a quantidade ideal de memória, assim como diferentes tipos usarão quantidades diferentes de memória.
Aqui está uma referência C # int do MSDN.
fonte
Integer
tipo de dados é de 32 bits em uma máquina de 32 bits e, aparentemente, será de 64 bits em uma máquina de 64 bits.int
é apenas uma abreviação deSystem.Int32
, não importa em que máquina o código seja executado.type int System.Int32
algo assim ou algo nesse sentido? Poderia ser alterado tão facilmente em uma versão futura do framework?uint
é um desses tipos não compatíveis, o que significa que não deve ser usado em API exposta publicamente para evitar a interrupção da capacidade de usar essa API em linguagens .NET diferentes daquela em que a biblioteca está escrita. É também por isso que a estrutura .NET A própria API está usando oint
queuint
faria.Os tipos inteiros não assinados devem ser usados apenas para representar números cardinais nos idiomas em que representam números cardinais. Devido à maneira como os computadores que executaram C funcionaram, os tipos inteiros não assinados se comportaram como membros dos anéis algébricos mod-2 ^ n (o que significa que os cálculos que estouraram estariam "encapsulados" previsivelmente) e o idioma especifica que, em muitos casos, esses tipos são deve se comportar como anéis algébricos abstratos, mesmo quando esse comportamento seria inconsistente com o comportamento de números cardinais ou números matemáticos.
Se uma plataforma oferecer suporte completo a tipos separados para números cardinais e anéis algébricos, sugiro que os números cardinais sejam processados usando tipos de números cardinais (e coisas que precisam ser agrupadas usando os tipos de toque). Esses tipos não apenas podiam armazenar números com o dobro do tamanho dos tipos assinados, mas um método que recebia um parâmetro desse tipo não precisaria verificar se era negativo.
Dada a relativa falta de tipos de números cardinais, no entanto, geralmente é melhor simplesmente usar números inteiros para representar números inteiros matemáticos e números cardinais.
fonte