/**
** You DO NOT want to do this usually...
**/
#include <stdint.h>
uint_fast64_t
concatIPv4Addr(uint_fast16_t parts[])
{
uint_fast64_t n = 0;
for (int i = 0; i < 3; ++i) {
n += parts[i];
n *= 1000;
}
return (n += parts[3]);
}
Я использовал «быстрые» целые типы для целей скорости, но если у вас есть требование к хранилищу, используйте вместо этого соответствующие «наименее» типы. Конечно, это предполагает, что у вас есть компилятор C99 или компилятор C89 с расширениями. В противном случае вы застряли в примитивных типах, где char
может даже быть 32-битным в соответствии со стандартом C. Поскольку я не знаю вашу целевую среду, я не сделал никаких предположений. Не стесняйтесь менять подходящие типы примитивов по своему усмотрению.
Я использовал 16-битовое значение (минимум), потому что 8-разрядное число может представлять только 0-255, а это означает, что если было введено 358 случайно, оно будет интерпретироваться как 102, которое все еще действует. Если у вас есть тип, способный хранить более 8 бит и менее 16 бит, вы, очевидно, можете использовать это, но тип должен иметь возможность хранить более 8 бит.
Это в стороне, вы должны по крайней мере, тип 38-разрядное:
4294967295 (32-bit unsigned max)
255255255255 (255.255.255.255 converted to the integer you want)
274877906944 (38-bit unsigned max)
Функция выше будет конвертировать 127.0.1.1 и 127.0.0.От 11 до 127000001001 и 127000000011, соответственно:
127.0.1.1 ->
127.000.001.001 ->
127000001001
127.0.0.11 ->
127.000.000.011 ->
127000000011
Почему так много нулей? Потому что иначе вы не можете сказать разницу между ними! Как говорили другие, вы можете смутить 127.0.1.1 и 127.0.0.11. Используя вышеприведенную функцию или что-то более подходящее, которое фактически преобразует адрес IPv4 в его реальное десятичное представление, у вас не будет такой проблемы.
Наконец, я не получил подтверждения на IPv4-адресе, переданном функции. Я предполагаю, что вы уже убедитесь, что адрес действителен до вызова каких-либо функций, которые сохраняют или используют IPv4-адрес. Кстати, если вы хотите сделать то же самое для IPv6, вы не можете так легко, потому что для этого потребуется строка или преобразование в десятичное число из каждой из 8 частей, каждая из которых не более 16 бит, что дает 5 десятичных цифр на каждую часть или 40 цифр. Чтобы сохранить это, вам потребуется не менее 133 бит, а не 128 бит, необходимых для адреса IPv6, так же, как вам потребуется 38 бит для хранения адреса IPv4 вместо 32 бит.
Все еще не так уж плохо, не так ли? Как насчет теоретического IPv8, где есть 16 частей, каждый из которых имеет 32-битный размер? Эквивалентная функция для вышеперечисленного потребует 580 бит вместо правильного математического требования: 512 бит. Хотя сегодня это не проблема, я просто указываю на ошибку при выполнении чего-либо с адресом IPv4, представленным объединением десятичных значений каждой части. Это ужасно ужасно.
Вы не можете, а не 32 бит. Но если у вас есть 64-битные целые числа, то вам нужна рутина, способная обрабатывать случай ведущих нулей (как только у вас это будет довольно просто). Как отмечено ниже, ваше преобразование также неоднозначно. Вместо этого вы можете использовать восьмеричную нотацию, если это применимо, которая будет вписываться в 32 бита в качестве бонуса: 'A: B: C: D -> A * 256^0 + B * 256^1 + C * 256^2 + D * 256^3', или вариант, основанный на конкретизации. – Thomas
Ваша проблема недостаточно определена. 11111 11.1.1.1 или 1.11.1.1 или 1.1.11.1 или 1.1.1.11? – bengoesboom
@Thomas, какие другие подходы я должен использовать, в основном я просто хочу создать int IP из строки, удалив '.' и преобразуя строку в целое. –