如何只将 12 位写入 C 中的 char 数组?

How to write only 12 bits to a char array in C?

我正在尝试实现一个 FAT12 文件系统,其中有一个 FAT table 数据结构,它是一个 unsigned char 数组。我需要编写一个函数,给定一个数组索引会将一个值写入接下来的 12 位(因为它是 FAT12),这非常棘手,因为部分值需要转到一个字节而另一部分需要转到一半第二个字节。

这是我想出的取值函数:

//FAT is the unsigned char array
int GetFatEntry(int FATindex, unsigned char * FAT) {
   unsigned int FATEntryCode; // The return value

   //   Calculate the offset of the WORD to get
   int FatOffset = ((FATindex * 3) / 2);

   if (FATindex % 2 == 1){   // If the index is odd

      FATEntryCode =  ((unsigned char)(&FAT[FatOffset])[0] + (((unsigned char)(&FAT[FatOffset])[1]) << 8));

      FATEntryCode >>= 4; // Extract the high-order 12 bits
   }
   else{    // If the index is even

      FATEntryCode = ((unsigned char)(&FAT[FatOffset])[0] + (((unsigned char)(&FAT[FatOffset])[1]) << 8));

      FATEntryCode &= 0x0fff; // Extract the low-order 12 bits
   }
   return FATEntryCode;
}

我正在努力想出一个函数来设置给定 FATindex 的值。如果有任何建议,我将不胜感激。

这似乎有效。应该写入的数据应该在data

的前12位
void WriteFatEntry(int FATindex, unsigned char * FAT, unsigned char data[2]) {
    //   Calculate the offset of the WORD to get                                                                   
    int FatOffset = ((FATindex * 3) / 2);

    unsigned char d;
    if (FATindex % 2 != 0){   // If the index is odd                                                               
// Copy from data to d and e, and shift everything so that second half of 
// e contains first half of data[1], and first half of e contains second
// half of data[0], while second half of d contains first half of data[0]. 
// First half of d contains a copy of first four bits in FAT[FatOffset]
// so that nothing changes when it gets written
        unsigned char e=data[1];
        e>>=4;
        d=data[0];
        e|=(d<<4) & 0b11110000;
        d>>=4;
        d |= FAT[FatOffset] & 0b11110000;

        FAT[FatOffset]=d;
        FAT[FatOffset+1] = e;
    }
    else{    // If the index is even                                                                               
        d = data[1] & 0b11110000;
        d |= FAT[FatOffset+1] & 0b00001111;

        FAT[FatOffset] = data[0];
        FAT[FatOffset+1] = d;
    }
}
#include <stdio.h>

#if 1 /* assuming MSB first */
#define MSB (idx)
#define LSB (idx+1)
#else /* assuming LSB first */
#define MSB (idx+1)
#define LSB (idx)
#endif

unsigned fat_getval(unsigned char * tab, unsigned num)
{
unsigned idx;
unsigned val;

idx = num + num/2;
val = (tab[MSB] <<8 ) + (tab[idx+1] ) ;
if (num %2 ==0) val >>= 4;

return val & 0xfff;
}

void fat_putval(unsigned char * tab, unsigned slot, unsigned val)
{
unsigned idx;

idx = slot + slot/2;
if (slot %2 ==0) {      /* xyz_ */
        val <<= 4;
        val |= tab[LSB] & 0xf;
        }
else    {               /* _xyz */
        val |= (tab[MSB] & 0xf0) << 8;
        }
tab[MSB] = val >>8;
tab[LSB] = val &0xff;
}
#undef MSB
#undef LSB

unsigned char fattable[] = "\x01\x23\x45\x67\x89\xab"; // 12 nibbles
int main(void)
{
unsigned idx, ret;
for (idx = 0; idx < 6; idx++) { // 6 bytes -> 12 nibbles */
        printf(" %02x", fattable[idx] );
        }
printf("\n");

printf("Put(0,0xabc):\n");
fat_putval(fattable, 0, 0xabc);
for (idx = 0; idx < 6; idx++) {
        printf(" %02x", fattable[idx] );
        }
printf("\n");

printf("Put(3,0xdef):\n");
fat_putval(fattable, 3, 0xdef);
for (idx = 0; idx < 6; idx++) {
        printf(" %02x", fattable[idx] );
        }
printf("\n");

printf("Get(0 to 4):\n");
for (idx = 0; idx < 4; idx++) { // 12 / 3 ~> 4 * 12bit entries
        ret = fat_getval( fattable, idx);
        printf("%u := %x\n", idx, ret );
        }
printf("\n");

return 0;
}