有没有更简单的方法来获取 char 数组的子字符串并将其转换为 C 中的 long?

Is there a simpler way to take a substring of an char array and convert it to a long in C?

我正在寻找一种shorter/more 优雅的方法来从接收到的 NTP 数据包中获取 NTP 时间戳。数据包存储在一个无符号字符数组 buf 中,来自套接字函数 recvfrom:

unsigned char buf[48];
recvfrom(sockfd, buf, 48, 0, (struct sockaddr *) &their_addr, &addr_len));

然后我将表示 32 位秒时间戳的第 40-43 个元素的值复制到一个无符号长 transSec 中,像这样进行位移:

recvPacket->transmitSec = buf[40];
recvPacket->transSec <<= 8;
recvPacket->transSec |= buf[41];
recvPacket->transSec <<= 8;
recvPacket->transSec |= buf[42];
recvPacket->transSec <<= 8;
recvPacket->transSec |= buf[43];

这很好用,但为了学习,是否有 shorter/more 优雅的方法来做到这一点?我试过 memcpy:

memcpy(&recvPacket->transSec, &buf[40], sizeof(unsigned long));

以及上述的一些其他变体,但得到的数字不正确。我对自己是否正确使用它不是特别有信心。

这实际上可能是一个 endianness 问题。在此处检查 wiki 条目:http://en.wikipedia.org/wiki/Endianness。简而言之,一种类型的字节顺序在一个系统和另一个系统之间不一定相同。看起来你在进行网络通信 - 查看字节顺序转换系列函数:

http://beej.us/guide/bgnet/output/html/multipage/htonsman.html

请注意,buf[40] 是流中的第一个字节,并且一直被移动到基础类型的最高字节。另一方面,memcpy 会将 buf[40] 复制到 transSec 的 0 偏移量中 - 实际上,字节顺序在您的两个示例中颠倒了。

您可以像这样在您的代码中检查它,您将声明一个字符指针(字符是 c 中最小的可寻址类型)并从您正在检查的地址开始遍历该类型的大小长度, 到地址+sizeof(type):

// declare a char *
char * walker;
// set it to your integer
walker = (char *)&(recvPacket->transSec);
for ( i = 0; i < sizeof(unsigned long); i++){
    // print out the bytes from memory address[0] - address[3] ( assuming 4-byte unsigned long)
    printf("%x\n", walker[i]);
}

你也可以像这样遍历 buff,但那已经是一个 char 缓冲区了,所以你还不如直接打印它。我想你会看到字节顺序颠倒了。