Dev-C++ особенности компилятора или массовое непонимание преобразования типов???
Код:
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]
...
movsx ebx, byte ptr [eax]
...
Т.е. поместит в addr.s_addr байт расширенный до двойного слова...
Может мне кто-нибудь объяснить это массовая ошибка авторов опусов или все же такая сборка это индивидуальная особенность Dev-C++????
P.S. Лично я всегда в таких ситуациях использовал такую конструкцию которая работала правильно:
Код:
addr.s_addr=*(unsigned long *)hp->h_addr_list[0]
Нужно смотреть на вещи с т.з. языка программирования, на котором программируешь.
Посмотри, что такое 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
00 00 00 01
| unsigned long | = 0x10000000
Оффтоп! - Диабло, автор опуса - случайно не Крис Касперски? Мне его статья по работе с сокетами как-то попадалась:).
Код:
unsigned long address;
struct hostent *hp;
hp=gethostbyname("www.yandex.ru");//к примеру
address=(unsigned long)hp->h_addr_list[0][0];
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
Цитата: Zorkus
Оффтоп! - Диабло, автор опуса - случайно не Крис Касперски? Мне его статья по работе с сокетами как-то попадалась:).
Разве оффтоп???
не... у Криса Касперски:
Код:
addr.sin_addr.s_addr=((unsigned long **)hst->h_addr_list)[0][0];
что неоднозначности не вызывает...
Цитата:
что 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 ++;
}
}
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 ++;
}
}
Код:
address=(unsigned long)hp->h_addr_list[0][0];
P.S. просто у меня компилятор beta версия... склонна глючить... задергала меня совсем, так я начинаю подозревать глюки на пустом месте...