Задать вопрос
trinitr0
@trinitr0
провинциальный админ

Что написано в строке указатель или ссылка?

Помогите пожалуйста разобраться в следующей строчке:

if ( connect (s, (struct sockaddr_in *)&serv_addr, sizeof_addr)) == -1 )
{...}


не совсем понимаю как интерпретировать этот кусок
(struct sockaddr_in *)&serv_addr
то ли указатель на сруктуру, то ли ссылка, то ли ещё что...
  • Вопрос задан
  • 162 просмотра
Подписаться 1 Оценить 2 комментария
Пригласить эксперта
Ответы на вопрос 3
@Mercury13
Программист на «си с крестами» и не только
Одно из двух.

а) Либо так называемый reinterpret_cast или type pun — берётся кусок памяти serv_addr неизвестного типа и рассматривается как совсем другой тип, sockaddr_in. Корректность такого «взять кусок памяти и рассмотреть как другой тип» остаётся за программистом, возможны тонкие ошибки кроссплатформенности.

б) (в данном примере, скорее всего, нет, но тоже бывает) Либо так называемый const_cast — переменную, отмеченную как const, мы рассматриваем как неконстантную того же типа. Опять-таки, корректность такого преобразования остаётся за программистом: если переменная окажется в неизменяемой памяти, а мы её решим изменить, будет нехорошо.

То и другое — либо сильно обобщённый код оперирует указателями «на что угодно», либо какая-то разглючка, либо плохая архитектура, либо последствия того, что где-то приходится опускаться на самый низкий уровень (обработка сообщений Windows, плагинная система).

Подобное преобразование типа выполнено в стиле Си (взять указатель на переменную и преобразовать в другой тип-указатель).

Кстати, в коде ещё одна ошибка кроссплатфроменности — константа -1 только для Linux. Портабельно — макрос SOCKET_ERROR.

UPD. Это именно что reinterpret в сильно обобщённом (и сильно системном) коде. Функция connect принимает указатель на кусок памяти, который состоит из двухбайтового названия протокола и сетевого адреса произвольной длины (тип sockaddr). Тип sockaddr_in — это как будет эта выглядеть эта память для адресов IPv4 (протокол AF_INET). Одна и та же функция connect может подключаться по IPv4, IPv6, Apple Talk, Bluetooth и куче других протоколов, ныне известных разве что историкам. Другой протокол, другое AF_, другие sockaddr. Так что берём версию для IPv4 (sockaddr_in), заполняем её и передаём в connect, преобразовав в «более общий» тип sockaddr. Опознав, что имеем дело с IPv4, функция connect снова проинтерпретирует эту память как sockaddr_in.
Ответ написан
@abcd0x00

не совсем понимаю как интерпретировать этот кусок
(struct sockaddr_in *)&serv_addr
то ли указатель на сруктуру, то ли ссылка, то ли ещё что...

Это берётся адрес структуры в памяти определённого размера и этот адрес приводится к типу адреса структуры другого размера. Адрес тот же самый остаётся, а размер данных по этому адресу как бы меняется. На самом деле она уже там лежит в правильном размере, просто сама структура является как бы составной. И чтобы компилятор не ругался, что структура не того типа подаётся, делается такое приведение.

В лине адреса делаются таким образом: берётся общая структура, которая подходит под все адреса, потом к ней в конце привязывается (дописывается в памяти) адрес в определённом виде. А так как адреса бывают разных размеров, то и размер конечной структуры может варьироваться. Сам язык по стандарту допускает дописывание в конец структуры каких-то данных, поэтому эта возможность языка и используется в POSIX-системах для составления адресов перед их использованием.
Ответ написан
Комментировать
teke_teke
@teke_teke
programador
берется адрес структуры "server_addr" и приводится к типу "указатель на структуру sockaddr_in"
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы