正如标题所述,我从gethostbyname
回来的数据似乎有一个错误的第一位。
这是一个简短的例子:
struct hostent* host= gethostbyname("indiana.cs.rit.edu");
if (!host)
exit(-1);
printf("%d.%d.%d.%d\n", (host->h_addr_list[0][0]),
(host->h_addr_list[0][1]),
(host->h_addr_list[0][2]),
(host->h_addr_list[0][3]));
printf("%d.%d.%d.%d\n",UP(host->h_addr_list[0][0]),
UP(host->h_addr_list[0][1]),
UP(host->h_addr_list[0][2]),
UP(host->h_addr_list[0][3]));
UP定义为
#define UP(X) (((int)X) & 0XFF)
上述代码的输出是:
-127.21.37.10
和129.21.37.10
。
现在我知道我应该使用inet_ntoa
获取我的char *版本的IP地址。但是,有谁知道为什么我的第一个字节被破坏了?由于我从host->h_addr_list
返回char **,我的第一个[]
应该尊重第一个地址,其中第二个[]
应该取消引用实际的char。假设char是1byte,为什么我必须执行按位运算符来清除损坏的位?
增加混乱的层次是我得到-127或129的原因。
例如,在二进制中,我的129对于一个字节应该看起来像..
1000 0001
但是,基于-127的值,它表明我的基础二进制值是。
1111 1111
现在,我真的感到困惑的是0XFF(1111 1111)的按位运算符如何返回129,因为我看到它应该返回255表示无符号或-127表示签名。额外数据来自哪里?
感谢您的帮助。
答案 0 :(得分:1)
host->h_addr_list[0][0]
会将符号扩展为有符号的int。
如果你这样做:
printf("%d.%d.%d.%d\n", (unsigned char)(host->h_addr_list[0][0]),
(unsigned char)(host->h_addr_list[0][1]),
(unsigned char)(host->h_addr_list[0][2]),
(unsigned char)(host->h_addr_list[0][3]));
然后你就不会有问题了。
在二进制补码(8位)129和-127具有相同的位模式并且您的分析错误。
11111111在8位有符号二进制补码(不是-127)中为-1,有符号8位数的范围为-128到127.
1000000 = -128 (128 unsigned)
1000001 = -127 (129 unsigned)
1000010 = -126 (130 unsigned) (etc)