4
回答
linuxC语言算法错误求解,为什么整形强制转换成字符型后是逆序的?
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   
这里有个简单的c语言算法,在Linux(x86 Ubuntu 32位)下编写和调试的,究其错误的原因,我竟不得其解,所以来向各位求助;


一个简单的算法:将一个int类型,保存了ip地址十六进制格式的变量内容,转换成字符串类型,即,int->char


比如192.168.1.1,十六进制就是0xc0a80101,转换后竟然成了1.1.168.192...


代码如下,希望知道的能详细解说一下.


#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

void ip_to_str(char *str, unsigned long ip)
{
	unsigned char c[4];
	unsigned char *p = (unsigned char *)&ip;

	c[0] = *(p++);
	c[1] = *(p++);
	c[2] = *(p++);
	c[3] = *(p);
	
	sprintf(str, "%d.%d.%d.%d", c[0],c[1],c[2],c[3]);
}

int main(int argc, char* argv[])
{
	int a = 0xc0a80101;
	char ipstr[16];
	bzero(ipstr, 16);
	ip_to_str(ipstr, a);

	printf("%s\n",ipstr);

	return 0;
}
举报
TymonHuang
发帖于5年前 4回/425阅
共有4个答案 最后回答: 5年前

ntohl 是将网络字节顺序(network byte order)转换为主机字节顺序(host byte order),我们常用的是 x86架构,也就是 little-endian,不管怎样,其实与这个函数是没有关系的。

0xc0a80101 存在4字节的整形变量中,我们看 Alphajay 的文章知道,它其实在内存里按照地址从低到高是这样的:01 01 a8 c0
于是根据字节顺序取出来就是反向的。

--- 共有 1 条评论 ---
TymonHuang我一直以为,将网络字节序转换为主机字节序后就会正确的了.原来不是这么回事..明白,谢谢. 嗯嗯,在ip_to_str加一个endian_check();小端则逆序取出.... 5年前 回复
big endian/little endian问题。这样转是不行的,建议你先搞清楚提到的这个问题。
--- 共有 1 条评论 ---
TymonHuang你好,不妨告诉你,我是在工作中遇到这个问题的.我socket上接收过来数据的时候,已经用ntohl()来转换过了,然后再用我上面说的这个ip_to_str()函数,为为什么还会出现这个现象?,,,, 5年前 回复

简单的说,取 IP 字节时,反向操作即可。

c[3] = *(p++);
c[2] = *(p++);
c[1] = *(p++);
c[0] = *(p);
延伸阅读:
http://my.oschina.net/alphajay/blog/5478
看完就明白了,如果需要跨硬件平台,需要检测 endian。

--- 共有 3 条评论 ---
有理想的猪回复 @banglang_huang : 不了解网络操作,不过在 PostgreSQL中用的是 send,不是 sendfile。另外,通过 ftp 之类直接copy一个大文件看看速度有多少,是不是受到网络环境的影响。 5年前 回复
TymonHuang你能帮我看看我提问的另外一个问题吗? linux c语言的sendfile函数. 5年前 回复
TymonHuang你好,我修改了提问的代码, 不妨告诉你,我是在工作中遇到这个问题的.我socket上接收过来数据的时候,已经用ntohl()来转换过了,然后再用我上面说的这个ip_to_str()函数,为为什么还会出现这个现象?,,,, 5年前 回复

引用来自“权宗亮”的答案

ntohl 是将网络字节顺序(network byte order)转换为主机字节顺序(host byte order),我们常用的是 x86架构,也就是 little-endian,不管怎样,其实与这个函数是没有关系的。

0xc0a80101 存在4字节的整形变量中,我们看 Alphajay 的文章知道,它其实在内存里按照地址从低到高是这样的:01 01 a8 c0
于是根据字节顺序取出来就是反向的。

谢谢你的回答, 我开始了解这个内容了,以前是一知半解.
顶部