So between 2^63 and 2^64-1, you get negative integers showing you how far off from ULONG_MAX you are.
Não. Como você descobre isso? Por seu próprio exemplo, o máximo é:
> max=$((2**63 - 1)); echo $max
9223372036854775807
Se "estouro" significa "você recebe números inteiros negativos mostrando o quão longe está de ULONG_MAX você está", então se adicionarmos um a isso, não deveríamos obter -1? Mas em vez disso:
> echo $(($max + 1))
-9223372036854775808
Talvez você queira dizer que esse é um número que você pode adicionar a $max
para obter uma diferença negativa, já que:
> echo $(($max + 1 + $max))
-1
Mas isso de fato não continua verdadeiro:
> echo $(($max + 2 + $max))
0
Isso ocorre porque o sistema usa o complemento de dois para implementar números inteiros assinados. < sup> 1 O valor resultante de um estouro NÃO é uma tentativa de fornecer a você uma diferença, uma diferença negativa, etc. É literalmente o resultado do truncamento de um valor para um número limitado de bits, em seguida, tê-lo interpretado como um inteiro assinado com um complemento de dois. Por exemplo, a razão $(($max + 1 + $max))
sai como -1 é porque o valor mais alto no complemento de dois é todos os bits definidos exceto o bit mais alto (que indica negativo); somar isso basicamente significa carregar todos os bits para a esquerda para que você fique com (se o tamanho fosse 16 bits e não 64):
11111111 11111110
O bit alto (sinal) agora está definido porque é transportado na adição. Se você adicionar mais um (00000000 00000001) a ele, então terá todos os bits definidos , que no complemento de dois é -1.
Acho que responde parcialmente à segunda metade da sua primeira pergunta - "Por que os inteiros negativos ... são expostos ao usuário final?". Primeiro, porque esse é o valor correto de acordo com as regras dos números de complemento de dois de 64 bits. Essa é a prática convencional da maioria das linguagens de programação de alto nível de propósito geral (não consigo pensar em uma que não faça isso), então bash
está aderindo à convenção. Qual é também a resposta à primeira parte da primeira questão - "Qual é a razão?": Esta é a norma na especificação de linguagens de programação.
WRT a segunda questão, eu não ouvi falar de sistemas que interativamente mudam ULONG_MAX.
Não faria qualquer diferença em como a aritmética sai, porque este não é um valor arbitrário que é usado para configurar o sistema - é um valor de conveniência que armazena uma constante imutável refletindo o hardware. Por analogia, você poderia redefinir c como 55 mph, mas a velocidade da luz ainda seja 186.000 milhas por segundo. c não é um número usado para configurar o universo - é uma dedução sobre a natureza do universo.If someone arbitrarily changes the value of the unsigned integer maximum in limits.h, then recompiles bash, what can we expect will happen?
ULONG_MAX é exatamente o mesmo. É deduzido / calculado com base na natureza dos números de N bits. Alterá-lo em limits.h
seria uma péssima ideia se essa constante fosse usada em algum lugar, supondo que ela representasse a realidade do sistema .
E você não pode mudar a realidade imposta pelo seu hardware.
1. Eu não acho que isso (o meio de representação inteira) é realmente garantido por bash
, uma vez que depende da biblioteca C subjacente e o padrão C não garante isso. No entanto, isso é o que é usado na maioria dos computadores modernos normais.