Другая общая версия примера Andrew, страшное двустишие кода
parent.addChild(child);
child.setParent(parent);
Вместо того, чтобы волноваться, делаются ли обе строки всегда вместе и в последовательном порядке, Вы могли бы сделать методы частными и сделать, чтобы друг функционировал для осуществления непротиворечивости:
class Parent;
class Object {
private:
void setParent(Parent&);
friend void addChild(Parent& parent, Object& child);
};
class Parent : public Object {
private:
void addChild(Object& child);
friend void addChild(Parent& parent, Object& child);
};
void addChild(Parent& parent, Object& child) {
if( &parent == &child ){
wetPants();
}
parent.addChild(child);
child.setParent(parent);
}
, Другими словами, можно сохранить открытые интерфейсы меньшими и осуществить инварианты, которые сокращают через классы и объекты в друге функции.
Вот простой способ сделать это: (ip >> 8)
, (ip >> 16)
и (ip >> 24)
перемещает 2-й, 3-й и 4-й байты в байт младшего порядка, в то время как & 0xFF
изолирует младший байт на каждом шаге.
void print_ip(unsigned int ip)
{
unsigned char bytes[4];
bytes[0] = ip & 0xFF;
bytes[1] = (ip >> 8) & 0xFF;
bytes[2] = (ip >> 16) & 0xFF;
bytes[3] = (ip >> 24) & 0xFF;
printf("%d.%d.%d.%d\n", bytes[3], bytes[2], bytes[1], bytes[0]);
}
Подразумевается bytes [0] = (ip >> 0) & 0xFF;
на первом этапе.
Используйте snprintf ()
, чтобы вывести его в строку.
Другой подход:
union IP {
unsigned int ip;
struct {
unsigned char d;
unsigned char c;
unsigned char b;
unsigned char a;
} ip2;
};
...
char ips[20];
IP ip;
ip.ip = 0xAABBCCDD;
sprintf(ips, "%x.%x.%x.%x", ip.ip2.a, ip.ip2.b, ip.ip2.c, ip.ip2.d);
printf("%s\n", ips);
Подсказка: разбейте 32-битное целое число на 4 8-битных целых и распечатайте их.
Что-то вроде этого (не скомпилировано, YMMV):
int i = 0xDEADBEEF; // some 32-bit integer
printf("%i.%i.%i.%i",
(i >> 24) & 0xFF,
(i >> 16) & 0xFF,
(i >> 8) & 0xFF,
i & 0xFF);
Это то, что я сделал бы, если бы передал строковый буфер для заполнения, и я знал, что буфер достаточно велик (т.е. не менее 16 символов):
sprintf(buffer, "%d.%d.%d.%d",
(ip >> 24) & 0xFF,
(ip >> 16) & 0xFF,
(ip >> 8) & 0xFF,
(ip ) & 0xFF);
Это было бы немного быстрее, чем сначала создать байтовый массив, и я думаю, это более читабельно. Обычно я использую snprintf, но IP-адреса не могут быть длиннее 16 символов, включая завершающий нуль.
В качестве альтернативы, если меня попросили функцию, возвращающую char *:
char* IPAddressToString(int ip)
{
char[] result = new char[16];
sprintf(result, "%d.%d.%d.%d",
(ip >> 24) & 0xFF,
(ip >> 16) & 0xFF,
(ip >> 8) & 0xFF,
(ip ) & 0xFF);
return result;
}
#include "stdio.h"
void print_ip(int ip) {
unsigned char bytes[4];
int i;
for(i=0; i<4; i++) {
bytes[i] = (ip >> i*8) & 0xFF;
}
printf("%d.%d.%d.%d\n", bytes[3], bytes[2], bytes[1], bytes[0]);
}
int main() {
int ip = 0xDEADBEEF;
print_ip(ip);
}