字节序的问题

本文解析了大字节序与小字节序的概念,并提供了VC++环境下通过位移操作和memcpy函数实现二者间转换的具体方法。

最近读shape文件,文档指出了大字节序(big endian)和小字节序(little endian) 。搜索引擎告诉我,这个东西原意是鸡蛋的大小两头,在计算机里是内存中是高低字节的排列方式而已;同时,又引出了有的机器是9位、12位等等为一字节的,这个我不想说了,对我完全没有意义。

其实,只要明白两个问题就行了:

1、vc++中,是小字节序的,一个字节8位,char 为一个字节,int为4个字节

2、大小转换的方法:

我有两个办法,一个是位移,一个使用memcpy其实很简单。

CFile file;
 CFileException e;

 if(file.Open("d://sss.shp",CFile::typeBinary | CFile::modeRead  ,&e))
 {

  char charBuffer[4];
   int a;
   file.Read(charBuffer,4);
 //  char charBuffer1[4];
   file.Seek(0,0);
  //高低位交换的两种方法
  // 方法1:位移
   file.Read(&a,4);
   int b1=0,b2=0,b3=0,b4=0;四个数每位都为0

int一共32位,先得到最后八位(b1),然后得到倒数第二个八位(b2)·······
把四个数相与即可

 b1=a>>24;
   b2=a>>16;
   b2=b2<<24;
   b2=b2>>16;
   b3=a>>8;
   b3=b3<<24;
   b3=b3>>8;
   b4=a<<24;
   a=b1|b2|b3|b4;
   
//方法2:用char类型交换
   /*
   int b=0;
      int c=0;
      
      c=a>>24&(~(~b<<24));
   
      memcpy(charBuffer,&a,4);
      for(int i=0;i<2;i++)
      {
       char j;
       j=charBuffer[i];
       charBuffer[i]=charBuffer[3-i];
       charBuffer[3-i]=j;
      }
      memcpy(&a,charBuffer,4);*/
   
  TRACE("%d",a);
 }

例子中打开的是一个shape文件,可以到网上找或者用esri 的 arcmap导出来一个。

位移的方法其实很简单,也就是大学时学谭浩强的c语言书上的位移举例一章的内容了。第二种方法其实更简单,

把一个整数截成4段(4个字节吗)放到四个cha中,然后倒个顺序,再拷回去,完事。劈开和合并时c++只能用memcpy函数了。

上面两种方法,据说位移更快些,快多少呢?我不知道了

至于牛人们还有用汇编的可能更简单些,不过我不会!

顺便提一句,谭浩强的c语言书是考二级用的!二级是某些城市进城要户口的最低标准,汗!

在UDP通信中,IP地址的字节序处理是一个关键问题。由于不同计算机体系结构可能存在字节序差异(大端或小端),因此在进行网络通信时,必须确保数据的一致性。IP地址本质上是一个32位的整数,在网络传输中按照大端字节序进行处理,即高位字节先传输[^3]。 ### IP地址的表示存储 IP地址在程序中通常以点分十进制字符串形式表示,例如 `192.168.1.1`。然而,在底层网络通信中,它需要被转换为一个32位的整数。这个整数在网络上传输时遵循大端字节序,即高位字节在前。为了实现这种转换,C语言中提供了 `inet_pton` 函数用于将字符串形式的IP地址转换为网络字节序的二进制形式[^1]。 例如,将 `192.168.1.1` 转换为网络字节序的32位整数后,其十六进制表示为 `0xC0A80101`,其中高位字节 `0xC0` 是第一个字节。 ### 主机字节序网络字节序的转换 由于主机的字节序可能是小端或大端,为了保证跨平台的一致性,程序中通常使用以下函数进行字节序转换: - `htonl()`:将32位整数从主机字节序转换为网络字节序。 - `htons()`:将16位整数从主机字节序转换为网络字节序。 - `ntohl()`:将32位整数从网络字节序转换为主机字节序。 - `ntohs()`:将16位整数从网络字节序转换为主机字节序。 在UDP通信中,发送端通常需要将IP地址和端口号转换为网络字节序,接收端则将其转换回主机字节序,以确保数据的正确解析。例如,端口号通常使用 `htons()` 转换为网络字节序后再填充到 `sockaddr_in` 结构体中。 ### 示例代码:UDP通信中的IP地址端口号处理 以下是一个简单的UDP发送端代码片段,展示了如何进行IP地址和端口号的字节序处理: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> int main() { int sockfd; struct sockaddr_in server_addr; char *ip = "192.168.1.1"; int port = 8080; // 创建UDP套接字 sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { perror("Socket creation failed"); exit(EXIT_FAILURE); } memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); // 将端口号转换为网络字节序 // 将IP地址从字符串转换为网络字节序的整数 if (inet_pton(AF_INET, ip, &server_addr.sin_addr) <= 0) { perror("Invalid address / Address not supported"); close(sockfd); exit(EXIT_FAILURE); } // 发送数据 const char *message = "Hello, UDP!"; sendto(sockfd, message, strlen(message), 0, (const struct sockaddr *)&server_addr, sizeof(server_addr)); printf("Message sent to %s:%d\n", ip, port); close(sockfd); return 0; } ``` ### 接收端处理 接收端在接收到数据后,通常需要将端口号从网络字节序转换回主机字节序,以进行服务匹配。例如: ```c struct sockaddr_in client_addr; socklen_t len = sizeof(client_addr); char buffer[1024]; int n = recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &len); buffer[n] = '\0'; // 将端口号转换回主机字节序 int client_port = ntohs(client_addr.sin_port); char client_ip[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &(client_addr.sin_addr), client_ip, INET_ADDRSTRLEN); printf("Received message from %s:%d\n", client_ip, client_port); ``` ### 总结 在UDP通信中,IP地址和端口号的字节序处理是确保跨平台兼容性的关键步骤。IP地址通过 `inet_pton` 转换为网络字节序的32位整数,端口号则通过 `htons` 和 `ntohs` 在主机网络字节序之间转换。这些操作保证了不同架构的主机之间可以正确地进行通信。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值