Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Dev-C++ особенности компилятора или массовое непонимание преобразования типов???

8.5K
03 сентября 2007 года
infernodiablo
73 / / 04.03.2006
Просматривая страницы интернета наткнулся на интересные опусы по программированию winsock. Меня заинтересовала строчка вида:
 
Код:
addr.s_addr=(unsigned long)hp->h_addr_list[0][0];//addr - struct in_addr, hp - struct hostent

Вроде бы все правильно, вот только компилятор Dev-C++ скомпилирует эту строчку примерно так:
 
Код:
...
movsx ebx, byte ptr [eax]
...

Т.е. поместит в addr.s_addr байт расширенный до двойного слова...
Может мне кто-нибудь объяснить это массовая ошибка авторов опусов или все же такая сборка это индивидуальная особенность Dev-C++????
P.S. Лично я всегда в таких ситуациях использовал такую конструкцию которая работала правильно:
 
Код:
addr.s_addr=*(unsigned long *)hp->h_addr_list[0]
3
03 сентября 2007 года
Green
4.8K / / 20.01.2000
Неоднократно говорил, что завязка ЯВУ и ассемблера, жесткое сопоставление одного другому - типичная ошибка.

Нужно смотреть на вещи с т.з. языка программирования, на котором программируешь.

Посмотри, что такое h_addr_list:
 
Код:
char FAR* FAR* h_addr_list;

Т.о. в первом приведенном тобой примере после первого разындексирования h_addr_list[0] получаем указатель на char*. После второго разындексирования получаем char. Далее приводим его к типу unsigned long. Здесь все правильно.

Во втором же примере после разындексирования и получения указателя char*, ты приводишь его к unsigned long* и потом разыменовываешь указатель. Это вкорне неверно. Т.к. char* ссылается на тип одной размерности, а unsigned long* - другой. В теории рискуешь получить совершенно другое значение:
 
Код:
|char|                = 0
  00  00  00  01
| unsigned long |     = 0x10000000
63
03 сентября 2007 года
Zorkus
2.6K / / 04.11.2006
Оффтоп! - Диабло, автор опуса - случайно не Крис Касперски? Мне его статья по работе с сокетами как-то попадалась:).
8.5K
03 сентября 2007 года
infernodiablo
73 / / 04.03.2006
Green, ты немного не понял, что в структуре hostent и преобразования типов то я отлично понимаю. Суть в том что несколько человек (или один - а остальные подражатели) в своих примерах работы с winsock получают, с помощью функции gethostbyname указатель на структуру hostent и ,предполагая, что h_length=4 (не учитывая что адрес может быть и не из 4 байт), т.е. указатели в h_addr_list указывают на массив из 4 байт, пытаются пропихать весь этот массив в переменную unsigned long:
 
Код:
unsigned long address;
struct hostent *hp;
hp=gethostbyname("www.yandex.ru");//к примеру
address=(unsigned long)hp->h_addr_list[0][0];

Но компилятор Dev-C++, которым я пользуюсь, все это скомпилирует не так, как задумал автор этого примера, а возмет из массива, на который указывает h_addr_list[0] первый байт, расширит его до типа long и запихает в переменную address. По моему - это вполне логичное поведение компилятора, ведь h_addr_list объявлен как char **... Так вот, меня интересует, чисто из любопытства, другие компиляторы поступят так же, или все же пропихают в address все 4 байта (т.е. работал ли этот пример у автора статьи :) )
P.S. простите за assembler, я просто хотел показать как поступит компилятор :D
8.5K
03 сентября 2007 года
infernodiablo
73 / / 04.03.2006
Цитата: Zorkus
Оффтоп! - Диабло, автор опуса - случайно не Крис Касперски? Мне его статья по работе с сокетами как-то попадалась:).


Разве оффтоп???
не... у Криса Касперски:

 
Код:
addr.sin_addr.s_addr=((unsigned long **)hst->h_addr_list)[0][0];

что неоднозначности не вызывает...
8.8K
03 сентября 2007 года
The_Ice
109 / / 04.04.2006
Цитата:

что h_length=4 (не учитывая что адрес может быть и не из 4 байт)


Хм, как по-вашему, на момент написания статей - IPv6 уже использовали?

Код:
void
show_ip( char * p_hostname)
{
  if( !p_hostname)
    return;
  HOSTENT * hst_entry = gethostbyname( p_hostname);
  if( !hst_entry)
  {
    cout << "gethostbyname( )" << endl;
    return;
  }
  cout << "Host entry name: " << hst_entry-> h_name << endl;
 
  unsigned long ** ppl_address = (unsigned long ** )hst_entry-> h_addr_list;
 
  while( ppl_address && *ppl_address)
  {
    in_addr addr;
    addr. S_un. S_addr = ** ppl_address;
    cout<< "IP: " << inet_ntoa( addr) << endl;
    ppl_address ++;
  }
}
вот эта вот функция пока что меня не подводила :)
8.5K
03 сентября 2007 года
infernodiablo
73 / / 04.03.2006
Всем sorry... тема раздута на пустом месте... Это я просто ступил... Никакой компилятор не запишет в
 
Код:
address=(unsigned long)hp->h_addr_list[0][0];
4 байта массива, а только один, расширенный до long, как и гласят правила приведения типов...
P.S. просто у меня компилятор beta версия... склонна глючить... задергала меня совсем, так я начинаю подозревать глюки на пустом месте...
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог