linux下c语言的大小端

近来在ubuntu下开发c,网络编程方面的,遇到网络字节序,和本地字节序 大小端的问题。

1、判断大小端的简单方法:

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

int main(void)
{
	unsigned int i = 1;
	if(*((char*)&i) == 0)
	{
		printf("this is big endian. \n");
	}
	else if(*((char*)&i) == 1)
	{
		printf(" this is little endian. \n");
	} 
	else
	{
		printf("sorry, i do not know . \n");
	}
	return 0;
}


结果是:(如图)

当然,windows和ubuntu系统都是little endian 系统。


分析:

整形变量 i 在内存中占4个字节,所以有 32位;下图中显示的是:每个字节是 8 位二进制的数字,用 2 位十六进制表示 。所以 0x 0000 0001,表示 32 位 二进制数字, 是变量 i 在内存中的表示。(16进制的8位表示的是内存中的4个字节)

而指针指向最低位,所以上面的程序可以检测大小端的问题。

并且如果是大端的话,当前地址加3位 (+ 3)便得到了最末位的数值,末位为 ‘01’。(下图中红笔的指向)


所以有下面的代码并且相应的结果是:

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

int main(void)
{
	unsigned long i = 1;
	if(*((char*)&i) == 1)
	{
		printf("this is little endian.\n");
		printf("i   == %p . %d, \n", ((char*)&i)+0, *(((char*)(&i))+0) );//
		printf("i+1 == %p . %d, \n" , ((char*)&i)+1, *(((char*)(&i))+1));//高一个字节
		printf("i+2 == %p . %d, \n" , ((char*)&i)+2, *(((char*)(&i))+2));//高二个字节
		printf("i+3 == %p . %d, \n" , ((char*)&i)+3, *(((char*)(&i))+3));//高三个字节
		
		printf("i-1 == %p . %d,\n", *(((char*)(&i))-1) , ((char*)&i)-1);//低一个字节
		printf("i+4 == %p . %d,\n", *(((char*)(&i))+4) , ((char*)&i)+4);//高四个字节
	}
	else if(*((char*)&i) == 0)
	{
		printf("this is big endian. \n");
	}
	else
	{
		printf("i do not know. \n");
	}
	return 0;
}


结果:

即:在 i 的指针,所指向的空间存储的是:0000 0001 ,高一个字节的位置存储的是 0000 0000,高两个字节,和高三个字节也是 0000 0000。

但是 高四个字节和低一个字节的位置存储的是 不定的数值。 

2、htonl()和ntohl()方法的学习

#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>

int main(void)
{
	unsigned long i = 1;
	if(*((char*)&i) == 1)
	{
		printf("this is little endian.\n");
	}
	else if(*((char*)&i) == 0)
	{
		printf("this is big endian. \n");
	}
	else
	{
		printf("i do not know. \n");
	}

	i = ntohl(i);
	printf("%lu \n", i);
	printf("%#x \n", i);
	printf("%#o \n", i);

	i = ntohl(i);
	printf("%lu \n", i);
	printf("%#x \n", i);
	printf("%#o \n", i);

	return 0;
}



结果为:


结果分析:
(1)、是把内存中的二进制:  00000000 00000000 00000000 00000001,
按照字节反转过来为: 00000001 00000000 00000000 00000000 ,

自然数2的24次方结果为16777216

转换成十进制为: 16777216;

转换成十六进制为:0x0100 0000;
转换成八进制为:o 010 0000 0000。(红色的0x和o代表是十六进制和八进制)
(2)、从两个方法来看,htonl和ntohl都是实现了反转;并且经过验证,上面的ntohl()方法,和htonl()方法,都可以互换;
所以两个方法内部的实现应该是一样。


版权声明:本文为yuyantai1234原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。