Во-первых, следует отметить, что ваше предположение, что int
в C имеет 16 битов, неверно.В большинстве современных систем int
является 32-битным типом, поэтому, если мы поменяем (а не перевернем, который принимает дополнение), байты 5, мы получим 83886080, а не 1280
Хорошо, как уже говорили другие, ntohl(htonl(5) + htonl(6))
оказывается таким же , что и 5 + 6, только потому, что у вас есть небольшие числа, сумма их обращений не переполняется.Выбрав большее число, вы сразу увидите разницу
Однако это свойство действительно сохраняется в дополнении единицы для систем, в которых значения хранятся в 2меньшие части, как в этом случае
В дополнение к ним каждый выполняет арифметику с переносом конца , распространяя перенос обратно к переносу. Это делает арифметику дополнения endianнезависимый , если имеется только один внутренний «разрыв переноса» (т. е. сохраненное значение разбивается на два отдельных блока) из-за «циклического переноса»
Предположим, у нас есть xxyy и zztt, тогда xxyy + zzttсделано так:
carry
xx yy
+ zz <───── tt
──────────────
carry aa bb
│ ↑
└─────────────┘
Когда мы переворачиваем чанки, yyxx + ttzz переносится так же.Поскольку xx, yy, zz, tt - это куски битов любой длины, это работает для смешанного порядкового номера PDP или когда вы сохраняете 32-разрядное число в двух 16-разрядных частях, 64-разрядное число в двух 32-разрядных частях...
Например:
- 0x7896 + 0x6987 = 0xE21D
- 0x9678 + 0x8769 = 0x11DE1 → 0x1DE1 + 1 = 0x1DE2
- 0x2345 + 0x9ABC = 0xBE01
- 0x4523 + 0xBC9A = 0x101BD → 0x01BD + 1 = 0x01BE
- 0xABCD + 0xBCDE = 0x168AB = 0x168AB = 0x168AB → 0x688AB = 0x168AB → 0x688AB = 0x168AB → 0x688AB = 0x168AB → 0x688AB → 0x688AB = 0x168AB
- 0xCDAB + 0xDEBC = 0x1AC67 → 0xAC67 + 1 = 0xAC68
Или приведенный выше пример Джона Кугельмана: 0x68 + 0x0B = 0x73;0x86 + 0xB0 = 0x136 → 0x36 + 1 = 0x37
Конечный перенос является одной из причин, по которой их дополнение было выбрано для контрольной суммы TCP, поскольку вы можете легко вычислить сумму с более высокой точностью.16-разрядные ЦП могут работать в 16-разрядных блоках, как обычно, но 32- и 64-разрядные ЦП могут добавлять 32- и 64-разрядные блоки параллельно, не беспокоясь о переносе, когда SIMD недоступна, как метод SWAR