(long *)(host->h_addr)
означает интерпретировать host->h_addr
как указатель на long
.Это не очень переносимо, но, по-видимому, long
имеет длину 32 бита в системе, для которой было написано.
Дополнительная звездочка в *(...)
разыменовывает то, что теперь является long
для назначения.Это эффективно копирует все четыре байта исходного массива char
в одно значение long
addr.sin_addr.s_addr
.Сравните с (long)(*host->h_addr)
, который будет копировать только первый элемент char
.
Эта техника крайне непереносима.Предполагается как размер, так и порядковый номер типа long
.У вас может возникнуть искушение взять подсказку из того факта, что s_addr
является uint32
, и сделать:
addr.sin_addr.s_addr = *(uint32_t *)(host->h_addr);
Это не намного лучше, потому что порядок байтов все еще подорван.Кроме того, uint32_t
гарантированно содержит не менее 32 бит.Это может быть любое большее число битов, которое вызовет неопределенное поведение, когда вы попытаетесь прочитать нераспределенную память с копией (представьте, что вы копируете 32-битные данные char
как 64-битное целое число).
Таместь два варианта:
Если ваш массив char
уже находится в правильном порядке байтов (т. е. вам все равно, если h_addr[0]
представляет старший или младший байт локального uint32_t
), используйте memcpy
:
memcpy(&(addr.sin_addr.s_addr), host->h_addr, 4);
Это, вероятно, тот подход, который вам нужен.Если, с другой стороны, вы хотите, чтобы h_addr[0]
всегда заканчивался старшим байтом, вам необходимо соблюдать порядковый номер вашей системы:
addr.sin_addr.s_addr = (host->h_addr[0] << 24) + (host->h_addr[1] << 16) + (host->h_addr[2] << 8) + (host->h_addr[3]);
Вероятно, должны быть некоторые приведения к uint32_t
по пути туда.