Writing integer values to a file in binary using C - c

I am trying to write 9 bit numbers to a binary file.
For example, i want to write the integer value: 275 as 100010011 and so on. fwrite only allows one byte to be written at a time and I am not sure how to manipulate the bits to be able to do this.

You have to write a minimum of two bytes to store a 9-bits value. An easy solution is to use 16 bits per 9 bits value
Choose a 16 bits unsigned type, eg uint16_t and store the 2 bytes
uint16_t w = 275;
fwrite(&w, 1, 2, myfilep);
Reading the word w, ensure it actually uses only its 9 first bits (bits 0~8)
w &= 0x1FF;
Note that you might have endianness issues if you read the file on another system that doesn't have the same endianness as the system that wrote the word.
You could also optimize that solution using 9 bits of a 16 bits word, then using the remaining 7 bits to store the first 7 bits of the next 9 bits value etc...
See this answer that explains how to work with bit shifting in C.

Related

System Verilog - Reading a line from testbench and splitting the data

I'm a beginner in SystemVerilog Programming. I have a file called "input.in" and it has around 32 bits of data. The value is present in only one line of the file.
The data once sent from the testbench must be split into an array or 4 variables, each containing only 8 bits of the input. Please. Somebody help me :(
I think, you want to split the 32 bits of data into 4 bytes of data.
Please try the following:
{>>{a,b,c,d}} = var_32_bit ; //a,b,c,d are 8 bits variable.
// var_32_bit is an array of 32 bits size or a 32-bit variable. {bit a[] or bit [31:0]}
Is this the one you need ?

zlib format : beginning 2 bytes

I read https://www.ietf.org/rfc/rfc1950.txt. Still I have some doubts.
Its mentioned that CINFO value can't be more than 7, but in one of my input to zlib inflate() function I have 0x68de as the first two bytes. I am getting uncompressed data without any error from zlib. Here 0x68 first four bits is 0110 second four bits are 1000 which means CINFO is 8. I think I am missing something here. Can anyone explain me about this beginning two bytes (0x68de) clearly.
No, for 0x68, CINFO is 6 and CM is 8. CM is bits 0 to 3, which are the low four bits, and CINFO is bits 4 to 7, which are the high four bits. Section 2.1 clearly describes the notation used in the document, and which bits are which.

Write 9 bits binary data in C

I am trying to write to a file binary data that does not fit in 8 bits. From what I understand you can write binary data of any length if you can group it in a predefined length of 8, 16, 32,64.
Is there a way to write just 9 bits to a file? Or two values of 9 bits?
I have one value in the range -+32768 and 3 values in the range +-256. What would be the way to save most space?
Thank you
No, I don't think there's any way using C's file I/O API:s to express storing less than 1 char of data, which will typically be 8 bits.
If you're on a 9-bit system, where CHAR_BIT really is 9, then it will be trivial.
If what you're really asking is "how can I store a number that has a limited range using the precise number of bits needed", inside a possibly larger file, then that's of course very possible.
This is often called bitstreaming and is a good way to optimize the space used for some information. Encoding/decoding bitstream formats requires you to keep track of how many bits you have "consumed" of the current input/output byte in the actual file. It's a bit complicated but not very hard.
Basically, you'll need:
A byte stream s, i.e. something you can put bytes into, such as a FILE *.
A bit index i, i.e. an unsigned value that keeps track of how many bits you've emitted.
A current byte x, into which bits can be put, each time incrementing i. When i reaches CHAR_BIT, write it to s and reset i to zero.
You cannot store values in the range –256 to +256 in nine bits either. That is 513 values, and nine bits can only distinguish 512 values.
If your actual ranges are –32768 to +32767 and –256 to +255, then you can use bit-fields to pack them into a single structure:
struct MyStruct
{
int a : 16;
int b : 9;
int c : 9;
int d : 9;
};
Objects such as this will still be rounded up to a whole number of bytes, so the above will have six bytes on typical systems, since it uses 43 bits total, and the next whole number of eight-bit bytes has 48 bits.
You can either accept this padding of 43 bits to 48 or use more complicated code to concatenate bits further before writing to a file. This requires additional code to assemble bits into sequences of bytes. It is rarely worth the effort, since storage space is currently cheap.
You can apply the principle of base64 (just enlarging your base, not making it smaller).
Every value will be written to two bytes and and combined with the last/next byte by shift and or operations.
I hope this very abstract description helps you.

Multiplication of two 32 bit numbers using only 8 bit numbers

I saw this interview question online and can't find a good method other than the usual additive methods.
Any suggestions if this can be done quicker using some bitshift / recursion or something similar ?
Bitshifting would be natural part of a solution.
To multiply a value a by an eight-bit value b, for each 1 bit in b, add up all the values of a multiplied by b with all other bits set to 0. For example, a * 10100001 = a * 10000000 + a * 00100000 + a * 00000001.
Taking this further, suppose we want to multiply 11001011 by 0010000, this is 11001011(bin) << 4(dec). Doing this on an eight-bit value gives you 10110000. You have also lost (8-4)=4 bits from the beginning. Hence you would also want to do 11001011(bin) >> 4(dec) to get 00001100 as a carry into the next "8-bit column" (assuming that we are using 8 columns to represent a 64-bit answer).
Recursion would not really be necessary. All you'd need is a loop through the 4 bytes of the first 32-bit number, with another loop through the 4 bytes of the second number inside, multiplying each pair of bytes together in turn and adding it to your solution.

Efficient way to create/unpack large bitfields in C?

I have one microcontroller sampling from a lot of ADC's, and sending the measurements over a radio at a very low bitrate, and bandwidth is becoming an issue.
Right now, each ADC only give us 10 bits of data, and its being stored in a 16-bit integer. Is there an easy way to pack them in a deterministic way so that the first measurement is at bit 0, second at bit 10, third at bit 20, etc?
To make matters worse, the microcontroller is little endian, and I have no control over the endianness of the computer on the other side.
EDIT: So far, I like #MSN's answer the best, but I'll respond to the comments
#EvilTeach: I'm not sure if the exact bit pattern would be helpful, or how to best format it with text only, but I'll think about it.
#Jonathan Leffler: Ideally, I'd pack 8 10-bit values into 10 8-bit bytes. If it makes processing easier, I'd settle for 3 values in 4 bytes or 6 values in 8 bytes (although the 2 are equivalent to me, same amount of 'wasted' bits)
Use bit 0 and 31 to determine endianness and pack 3 10-bit values in the middle. One easy way to test matching endianness is to set bit 0 to 0 and bit 31 to 1. On the receiving end, if bit 0 is 1, assert that bit 31 is 0 and swap endianness. Otherwise, if bit 0 is 0, assert that bit 31 is 1 and extract the 3 values.
You can use bitfields, but the ordering within machine words is not defined:
That said, it would look something like:
struct adc_data {
unsigned first :10;
unsigned second :10;
unsigned third :10;
};
EDIT: Corrected, thanks to Jonathan.
The simplest thing to do about endian-ness is to simply pick one for your transmission. To pack the bits in the transmission stream, use an accumulator (of at least 17 bits in your case) in which you shift in 10 bits at a time and keep track of how many bits are in it. When you transmit a byte, you pull a byte out of the accumulator, subtract 8 from your count, and shift the accumulator by 8. I use "transmit" here loosely, your probably storing into a buffer for later transmission.
For example, if transmission is little endian, you shift in your 10 bits at the top of the acccumator (in its MS bits), and pull your bytes from the bottom. For example: for two values a and b:
Accumulator Count
(MS to LS bit)
aaaaaaaaaa 10 After storing a
aa 2 After sending first byte
bbbbbbbbbbaa 12 After storing b
bbbb 4 After sending second byte
Reception is a similar unpacking operation.

Resources