2015-02-07 2 views
2

Я сохранил файл в двоичном файле, и я могу получить этот размер файла в буфер char[8]. Я хотел был бы преобразовать этот char[] в тип off_t, чтобы иметь возможность передать его в качестве аргумента truncate(const char *path, off_t length).Convert char [] to off_t

Я пробовал этот наивный подход и, похоже, работает большую часть времени, но иногда он терпит неудачу и дает мне странную последовательность бит.

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; 
} 
+2

Преобразовать 'ул [я]' в какой-то знака: '= | в отставке (без знака) ул [я];' – pmg

+1

Вы знаете, если ваши компиляторы 'char' тип подписан или без знака? Это может иметь какое-то отношение к нему, так же как и фактическое * запись * в файл. –

+0

@pmg> Это не похоже на работу. Преобразование не выполняется. – user1527491

ответ

1

ret |= str[i]; является проблемой, так как str[i] может подписаться продлить при преобразовании в int, устанавливая множество бит в ret. Содержится @pmg и прокомментированы @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; 
} 
+2

Примечание: более педантичное решение будет использовать 'ret << = CHAR_BIT;' поскольку ширина 'char' не всегда 8 бит. Увидев, как OP сохраненный 'str', будет уточнять детали. – chux

-1

Предполагая, что файл, который содержит размер файла был создан на той же машине ТОЧНОЙ И что она изначально была написана с off_t типа, вы можете просто бросить char[] -> в off_t. например:

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

Вероятно, вы имели в виду '... = * ((off_t *) str);'? – alk

+0

Я сделал - спасибо – user590028

+0

Если вы тоже сейчас отрегулируете свою формулировку, это будет правильный ответ ... вы не переходите к 'off_t', а к' off_t *'. – alk

1

Просто насыпной скопируйте данные в вопрос:

#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); 

Чтобы обойти любые вопросы endiness просто сделать:

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

Как ntohll() нестандартно смотрите некоторые возможные способы его реализации здесь: 64 bit ntohl() in C++?

+0

Почему это должно быть лучше, чем литье (ответ user59002)? Это более длинный тип и медленнее. –

+0

@ user36740: Я не сказал, что это лучше или стоит того. – alk

+0

У этого есть проблема с контентом. –

0
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); 

выходы (на моей машине intel): ffeeeebbddaaeedd

что за wha ?! вы говорите .... есть проблема с этим подходом, и это то, что он не переносится ... это проблема с 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

+0

У этого есть проблема выравнивания. 'scalar' может быть более ограничительным, чем' blah'. – chux

+0

Незначительный: поскольку размер 'off_t' не обязательно совпадает с' unsigned long long', используется 'printf ("% llx \ n ", (unsigned long long) * scalar);' переносимо. Также подписан 'off_t'. – chux

+0

Если вы не знаете endianess, данные были сохранены, у вас есть ** нет ** 100% шанс правильно прочитать данные. – alk