ИЗМЕНЕНО ДЛЯ ДОБАВЛЕНИЯ ЛУЧШЕГО ОТВЕТА
Судя по комментариям, вы хотите сжать буфер - массив 16-битных целых, удалив 4 бита и собрав их вместе, верно?
Этот код должен помочь:
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <stdio.h>
typedef unsigned int UINT32 ;
typedef unsigned short UINT16 ;
void compress( UINT16 *buf , int *cnt )
{
UINT16 *src = buf ; // where we're copying from
UINT16 *tgt = buf ; // where we're copying to
UINT16 *limit = buf + *cnt ; // endpoint address
UINT16 bits = 0x0000 ;
int state = 0 ;
while ( src < limit )
{
switch ( state )
{
case 0 :
bits = (*src++ & 0x0FFF ) << 4 ;
state = 1 ;
break ;
case 1 :
bits |= (*src & 0x0F00 ) >> 8 ;
*tgt++ = bits ;
bits = (*src++ & 0x00FF ) << 8 ;
state = 2 ;
break ;
case 2 :
bits |= (*src & 0x0FF0 ) >> 4 ;
*tgt++ = bits ;
bits = (*src++ & 0x000F ) << 12 ;
state = 3 ;
break ;
case 3 :
bits |= (*src++ & 0x0FFF ) ;
*tgt++ = bits ;
bits = 0x000 ;
state = 0 ;
break ;
}
}
if ( state != 0 )
{
*tgt++ = bits ;
}
// hand back the new size ;
*cnt = (tgt - buf ) ;
while ( tgt < limit )
{
*tgt++ = 0x0000 ;
}
return ;
}
int main( int argc, char* argv[])
{
UINT16 buf[] = { 0xF123 , 0xE456 , 0xD789 , 0xCABC , 0xBDEF , } ;
int bufl = sizeof(buf) / sizeof(*buf) ;
compress( buf , &bufl ) ;
// buf now looks like { 0x1234 , 0x5678 , 0x9ABC , 0xDEF0 , 0x0000 }
return 0 ;
}
ОРИГИНАЛЬНЫЙ ОТВЕТ
Если вы действительно хотите прочитать 16-битные структуры из файла, которые имеют 12 интересных битов и 4 неиспользуемых (или не очень интересных) бита, и вы хотите избежать сдвоения битов, вы можете используйте битовые поля .
Обратите внимание, что реализации в соответствии со стандартом получают лот свободы в соответствии со стандартом, поэтому он не является переносимым по меньшей мере: вам, вероятно, потребуется настроить выравнивание структуры и, возможно, порядок полей, в зависимости от базовый процессор. Вы заметите, что я использовал #pragma pack(2)
для приведения структуры в 16-битный размер & mdash; это работает в Visual Studio 2010 C ++. YMMV и все такое.
[Вы уверены Вы не хотите просто маскировать биты, которые вам не нужны?]
В любом случае, как только вы разберетесь со всем этим, у вас должно работать что-то вроде следующего кода:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#pragma pack(2) // necessary to get correct alignment
typedef struct
{
unsigned short unused : 4 ;
unsigned short value : 12 ;
} CHUNK ;
#define BUFFER_CHUNKS ((size_t)8192)
void process( FILE*input )
{
CHUNK *buf = (CHUNK*) calloc( BUFFER_CHUNKS , sizeof(CHUNK) ) ;
size_t bufl = BUFFER_CHUNKS * sizeof(CHUNK) ;
int chunks = 0 ;
while ( 0 > (chunks=(int)fread( (void*)buf , sizeof(CHUNK) , BUFFER_CHUNKS , input ) ) )
{
for ( int i = 0 ; i < chunks ; ++i )
{
int value = buf[i].value ;
printf( "%d: %d\n" , i , value ) ;
}
}
return ;
}
Удачи!