将 char[] 转换为 off_t

Convert char[] to off_t

我在二进制文件中存储了一个文件大小,我能够将这个文件大小放入 char[8] 缓冲区。我想将此 char[] 转换为 off_t 类型,以便能够将其作为 truncate(const char *path, off_t length).

的参数传递

我尝试了这种天真的方法,它似乎大部分时间都有效,但有时会失败,并给我一个奇怪的位序列。

off_t pchar_2_off_t(char* str, size_t size)
{
    off_t ret = 0;
    size_t i;
    for (i = 0; i < size; ++i)
    {
        ret <<= 8;
        ret |= str[i];
    }
    return ret;
}

假设包含文件大小的文件是在完全相同的机器上创建的,并且它最初是用 off_t 类型编写的,您可以只转换 char[] -> off_t.例如:

off_t filesize = *((off_t*)str);

只需批量复制有问题的数据:

#include <string.h> /* for memcpy() */

...

char str[8];
/* Read 8 bytes binary data into str here. */

off_t off_file;
memcpy(&off_file, str, sizeof off_file);

要解决任何终端问题,只需执行以下操作:

off_t off = ntohll(off_file); /* Assuming ntohll being the 64bit version of ntohl(). */

由于 ntohll() 是非标准的,请在此处查看一些可能的实现方法:64 bit ntohl() in C++?

unsigned const char blah[8] = {0xdd,0xee,0xaa,0xdd,0xbb,0xee,0xee,0xff};
off_t * scalar = (off_t *) malloc(8);
memcpy(scalar, blah, 8);

printf("%llx\n",*scalar);

输出(在我的英特尔机器上):ffeeeebbddaaeedd

什么什么?!你说....这种方法有问题,它不可移植...这是 endianness 的问题...

因此,如果您想以可移植的方式执行此操作,您实际上需要了解字节顺序和特殊情况,或者只是通过循环进行转换:

*scalar = 0;
for (int i = 0; i < 8; i++)
{
    *scalar += (uint64_t)blah[i] << ( 8 * (7-i));
}

printf("%llx\n",*scalar);

输出(在所有具有 64 位 off_t 的机器上):ddeeaaddbbeeeeff

ret |= str[i]; 是一个问题,因为 str[i] 可能会在转换为 int 时进行符号扩展,在 ret 中设置许多位。由 @pmg and commented by @mafso

暗示
off_t pchar_2_off_t(const char* str, size_t size) {
    off_t ret = 0;
    size_t i;
    for (i = 0; i < size; ++i) {
        ret <<= 8;
        ret |= (unsigned char) str[i];
    }
    return ret;
}