I want to encode tags that will contain a field number and a wire type for the purpose of protocol buffers. The problem that I am having now is that whenever my value for 'tag' is below '8' fprintf writes additional values next to the correct ones. i.e. instead of 38 it prints 38c0 3. If the value of tag is 8 or higher the script works fine. Below is the code with irrelavent lines omitted.
int uint32_pack (uint8_t *fieldnumber, uint32_t value, uint8_t *out);
int main(){
uint32_t initvalue = 2;
int return_rv;
uint8_t *tag = (uint8_t *) malloc(sizeof(uint8_t));
uint8_t *tempout= (uint8_t *) malloc(sizeof(uint32_t));
*tag = 7; //value to be encoded (won't work for values less than 8)
return_rv = uint32_pack (tag, initvalue, tempout);
free(tempout);
}
/* === pack() === */
/* Pack an unsigned 32-bit integer in base-128 encoding, and return the number
of bytes needed: this will be 5 or less. */
int uint32_pack (uint8_t *fieldnumber, uint32_t value, uint8_t *out)
{
unsigned rv = 0;
FILE *wiretypetag;
int secondaryvalue;
wiretypetag = fopen("wiretype.txt","w");
//encodes wire type and the field number
if (*fieldnumber <16){
*fieldnumber <<= 3;
fprintf(wiretypetag,"%x",fieldnumber[0]);
}
if (*fieldnumber < 32 && *fieldnumber > 15){
*fieldnumber <<= 3;
secondaryvalue = 0x01;
fprintf(wiretypetag,"%x %x",fieldnumber[0],secondaryvalue);
}
if (*fieldnumber < 48 && *fieldnumber > 31){
*fieldnumber += 0x10;
*fieldnumber &= 0x1F;
*fieldnumber <<= 3;
secondaryvalue = 0x02;
fprintf(wiretypetag,"%x %x",fieldnumber[0], secondaryvalue);
}
if (*fieldnumber < 64 && *fieldnumber > 47){
*fieldnumber &= 0x1F;
*fieldnumber <<= 3;
secondaryvalue = 0x03;
fprintf(wiretypetag,"%x %x",fieldnumber[0], secondaryvalue);
}
/* assert: value<128 */
out[rv++] = value;
if (rv == 1){
fprintf(outfile,"%x",out[0]);
}
if (rv == 2){
fprintf(outfile,"%x %x",out[0], out[1]);
}
if (rv == 3){
fprintf(outfile,"%x %x %x",out[0],out[1],out[2]);
}
if (rv == 4){
fprintf(outfile,"%x %x %x %x",out[0],out[1],out[2],out[3]);
}
if (rv == 5){
fprintf(outfile,"%x %x %x %x %x",out[0],out[1],out[2],out[3],out[4]);
}
fclose(wiretypetag);
return rv;
}
if (fieldnumber <16){
should be
if (*fieldnumber <16){
You can simplify the code by using else at:
//encodes wire type and the field number
if (*fieldnumber <16){
*fieldnumber <<= 3;
fprintf(wiretypetag,"%d",fieldnumber[0]);
}
if (*fieldnumber < 32 && *fieldnumber > 15){
*fieldnumber <<= 3;
Replace with:
//encodes wire type and the field number
if (*fieldnumber < 16) {
*fieldnumber <<= 3;
fprintf(wiretypetag, "%d", fieldnumber[0]);
}
else if (*fieldnumber < 32) {
*fieldnumber <<= 3;
...
This is a common idiom and one you should use when appropriate - as now. It will improve the legibility of the code.
That may not be the whole problem; it probably isn't.
Explanation of Problem
In fact, using an else if chain corrects the code. Because the first if modifies *fieldnumber with the <<= operator, when the second condition is evaluated, *fieldnumber is no longer 7 but 56, so the condition for
if (*fieldnumber < 64 && *fieldnumber > 47){
is also executed, printing out more information.
The else if chain will resolve that by ensuring that only one alternative is executed.
Since you have:
unsigned rv = 0;
[...]
/* assert: value<128 */
out[rv++] = value;
if (rv == 1){
fprintf(outfile,"%x",out[0]);
}
This fprintf() should be executed, but the following ones for rv equal to 2, 3, 4, 5 should never be executed.
Related
I have a uint8_t array of size n>1 and would like to cast it into a uint16_t array of the same size n>1. I actually use the uint8_t array for ASCII characters and would like to use now UNICODE.
Any ideas how this conversion can be done?
Edit:
I would like to use this function here, which works fine for const char *string as argument and not for const uint16_t *string. So somehow I need to cast it.
srv_err_t gui_write_text_16bit(const uint16_t *string, Layout_type_t layout,
Layout_field_t field, Text_inverted_t inv) {
srv_err_t err;
uint8_t charCount;
uint8_t byteCount;
uint16_t bitmapCol = 0;
uint16_t bitmapRow = 0;
uint8_t textLength = 0;
uint8_t textHeight = GUI_FONT_NAME.FontHeight;
uint16_t offset;
uint8_t mask;
lcd_rectangle_t position;
if (LAYOUT_A == layout) {
if (LAYOUT_FIELD6 == field) {
// Position 6 is not available in Layout A
err.bits.input_parameter = true;
return err;
}
}
GUI_CONST_STORAGE GUI_CHARINFO
*pcharInfo;
GUI_CONST_STORAGE
unsigned char* pchar;
GUI_CONST_STORAGE GUI_FONT_PROP
*pfontProp;
//uint8_t textBitmap [bitmapLength * textHeight];
uint8_t textBitmap[(LCD_COLUMN_NUMBER_DISPLAY / 8) * GUI_FONT_HEIGHT] = { 0 };
/* Calculate needed space in the array */
// for (charCount = 0; charCount < stringLength; charCount++)
for (charCount = 0; string[charCount] != '\0'; charCount++) {
pfontProp = GUI_FONT_NAME.FontProp;
while (0 != pfontProp) {
if (pfontProp->First <= string[charCount]
&& pfontProp->Last >= string[charCount]) {
offset = string[charCount] - pfontProp->First;
pcharInfo = (pfontProp->pCharInfoFirstChar) + offset; // Pointer to the right character
textLength += pcharInfo->XSize; // Text length in Pixels
break; // exit while loop and beginn with next character
}
pfontProp = pfontProp->pNext;
}
}
textLength = (textLength / 8) + 1; // Text length in Bytes
// for(charCount = 0; charCount < stringLength; charCount++)
for (charCount = 0; string[charCount] != '\0'; charCount++) {
pfontProp = GUI_FONT_NAME.FontProp;
while (0 != pfontProp) {
if (pfontProp->First <= string[charCount]
&& pfontProp->Last >= string[charCount]) {
// Character in Range found
offset = string[charCount] - pfontProp->First;
pcharInfo = (pfontProp->pCharInfoFirstChar) + offset; // Pointer to the right character
pchar = pcharInfo->pData;
for (bitmapRow = 0; bitmapRow < textHeight; bitmapRow++) {
uint16_t bitmapByte = 0;
uint16_t charByte = 0;
uint8_t pixelShift;
for (byteCount = 0; byteCount < pcharInfo->BytesPerLine;
byteCount++) {
//bitmapByte = bitmapRow * bitmapLength + (bitmapCol / 8) + byteCount;
bitmapByte = bitmapRow * textLength + (bitmapCol / 8) + byteCount;
charByte = pcharInfo->BytesPerLine * bitmapRow + byteCount;
pixelShift = bitmapCol % 8;
if (byteCount == (pcharInfo->BytesPerLine - 1)) {
// Last Byte in row
switch (pcharInfo->XSize % 8) {
case 1:
mask = 0x80;
break;
case 2:
mask = 0xC0;
break;
case 3:
mask = 0xE0;
break;
case 4:
mask = 0xF0;
break;
case 5:
mask = 0xF8;
break;
case 6:
mask = 0xFC;
break;
case 7:
mask = 0xFE;
break;
case 0:
mask = 0xFF;
break;
default:
break;
}
textBitmap[bitmapByte] |= (pchar[charByte] & mask) >> pixelShift;
textBitmap[bitmapByte + 1] |= (pchar[charByte] & mask)
<< (8 - pixelShift);
//bitmapCol += pcharInfo->XSize % 8;
} else {
/* charByte is not aligned with the bitmapByte. A direct copy is not possible */
textBitmap[bitmapByte] |= pchar[charByte] >> pixelShift;
textBitmap[bitmapByte + 1] |= pchar[charByte]
<< (8 - pixelShift);
}
}
}
bitmapCol += pcharInfo->XSize;
break; // exit while loop and beginn with next character
}
pfontProp = pfontProp->pNext;
}
}
if (layout == LAYOUT_A) {
position = Layout_A_Text_Field[field];
/* place Bitmap on the right display Position */
if (LAYOUT_TITLE == field) {
gui_place_text(&position, textLength, textHeight, ALIGN_CENTER);
} else {
gui_place_text(&position, textLength, textHeight, ALIGN_LEFT);
}
if (LAYOUT_FIELD2 == field) {
lcd_draw_text(position, textBitmap, sizeof(textBitmap),
Layout_A_Field[field], DRAW_INVERSE);
} else {
lcd_draw_text(position, textBitmap, sizeof(textBitmap),
Layout_A_Field[field], DRAW_NORMAL);
}
}
return err;
}
Casting would be non sense because each element in a char array uses 1 single byte while 2 are needed for a UNICODE uint16_t array. But provided your initial string is composed of only ASCII or Latin1 characters, you can use the fact the the unicode code point of an ASCII or Latin1 character is just the character value.
So if the resulting array is allocated in caller, you could use code as simple as:
// Convert an ASCII or Latin1 string to a 16bits unicode string:
void tounicode(uint16_t *dest, const char *src, size_t nchars) {
while(nchars-- > 0) { // process nchars characters
*dest++ = (unsigned char) *src++; // one at a time
}
}
If you are using x86 hardware check out the SSE2 routines that convert a 16-byte vector into two 8-element uint16 vectors, in 2 machine ops. _mm_unpacklo_epi8() and ...unpackhi...
I wrote the following code to list all the prime numbers upto 2 billion using Sieve's method. I used bitmasking for flagging purpose. While I am able to get the prime numbers correctly, a few primes in the beginning are missing every time. Please help me find the bug in the program.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define MAX 2000000000
char* listPrimes(){
int block = sqrt(MAX);
char* mark = calloc((MAX/8),sizeof(char));
int i = 2;
int j;
char mask[8];
for(j=0;j<8;j++)
mask[j] = 0;
mask[7] = 1;
mask[6] |= mask[7] << 1;
mask[5] |= mask[7] << 2;
mask[4] |= mask[7] << 3;
mask[3] |= mask[7] << 4;
mask[2] |= mask[7] << 5;
mask[1] |= mask[7] << 6;
mask[0] |= mask[7] << 7;
for(j=0;j<8;j++)
printf("%d ",mask[j]);
mark[0] |= mask[0];
mark[0] |= mask[1];
while (i < block){
for (j = 2; i*j <= block; j++)
mark[(i*j) / 8] |= mask[((i*j) % 8 )];
i++;
}
printf("\n");
printf("The block size is\t:\t%d\n",block);
j = 2;
while(j<=block){
if((mark[j / 8] & mask[j]) == 0 ){
for(i = 2;i <= MAX; i++){
if((i%j) == 0){
mark[i / 8] |= mask[(i % 8)];
}
}
}
while((mark[++j / 8] & mask[j % 8]) != 0);
}
for(j=0;j<=MAX;j++)
if((mark[j / 8] & mask[(j % 8)]) == 0)
printf("%d\n", ((8*(j / 8)) + (j % 8)));
return mark;
}
int main(int argc,char* argv[]){
listPrimes();
return 0;
}
As ArunMK said, in the second while loop you mark the prime j itself as a multiple of j. And as Lee Meador said, you need to take the modulus of j modulo 8 for the mask index, otherwise you access out of bounds and invoke undefined behaviour.
A further point where you invoke undefined behaviour is
while((mark[++j / 8] & mask[j % 8]) != 0);
where you use and modify j without intervening sequence point. You can avoid that by writing
do {
++j;
}while((mark[j/8] & mask[j%8]) != 0);
or, if you insist on a while loop with empty body
while(++j, (mark[j/8] & mask[j%8]) != 0);
you can use the comma operator.
More undefined behaviour by accessing mark[MAX/8] which is not allocated in
for(i = 2;i <= MAX; i++){
and
for(j=0;j<=MAX;j++)
Also, if char is signed and eight bits wide,
mask[0] |= mask[7] << 7;
is implementation-defined (and may raise an implementation-defined signal) since the result of
mask[0] | (mask[7] << 7)
(the int 128) is not representable as a char.
But why are you dividing each number by all primes not exceeding the square root of the bound in the second while loop?
for(i = 2;i <= MAX; i++){
if((i%j) == 0){
That makes your algorithm not a Sieve of Eratosthenes, but a trial division.
Why don't you use the technique from the first while loop there too? (And then, why two loops at all?)
while (i <= block){
if ((mark[i/8] & mask[i%8]) == 0) {
for (j = 2; i*j < MAX; j++) {
mark[(i*j) / 8] |= mask[((i*j) % 8 )];
}
}
i++;
}
would not overflow (for the given value of MAX, if that is representable as an int), and produce the correct output orders of magnitude faster.
Change the middle loop to add the modulo:
j = 2;
while(j<=block){
if((mark[j / 8] & mask[j % 8]) == 0 ){
for(i = 2;i <= MAX; i++){
if((i%j) == 0){
mark[i / 8] |= mask[(i % 8)];
}
}
}
}
In the second while loop you are looping through i from 2 onwards and you do an if (i%j == 0). This will be true for i when it is a prime as well. You need to check for (i != j). Also the modulo as reported above. Hence it becomes:
if ((i%j == 0) {
if (i!=j)
mark[i/j] |= mask[i%j];
}
I have got an array of chars that I'm trying to bitwise shift right >>, then & with another array. I think I have got the wrong idea of how to do this.
I thought, even though it was an array of chars just stating my_array >>= 1 would shift everything but I am getting an error: "error: invalid operands to binary >> (have ‘char[8]’ and ‘int’)"
The bitwise comparision I am trying to do is with a similar size array initiated to all "0's"...for that I'm getting: "error: invalid operands to binary & (have ‘char *’ and ‘char *’)"
Do I need to convert these array's into something else before I can shift and compare?
Sorry, I was not super clear... All great advice up to this point and I think I am realizing more that there is no super easy way to do this. More specifically, what I am trying to do is shift the bits of the WHOLE char array right 1, adding the bit shifted off the right back to the left most side of the array, do the bitwise compare with another array of same size.
Technically the compare doesn't have to be array with array... I just need the bits. Would it be easier to convert the array's to something else before trying to do the shifts/comparisons?
You have to shift and compare elementwise.
for(i = 0; i < len; ++i)
array[i] >>= 3;
for example. If you want to move the bits shifted out of one element to the next, it's more complicated, say you're shifting right, then
unsigned char bits1 = 0, bits2 = 0;
for(i = len-1; i >= 0; --i) {
bits2 = array[i] & 0x07;
array[i] >>= 3;
array[i] |= bits1 << 5;
bits1 = bits2;
}
traversing the array in the other direction because you need the bits from the next higher slot.
You'll have to shift the entries in the array one by one. (And if you want to compare two of these, you'll need to do it element by element.)
If you were hoping that bits shifted off each char would get shifted into the next one, you'll need to take care of that manually too.
If you are wanting that shift-into-the-next-byte behaviour, and don't mind making your code nasty and nonportable and bug-prone, you might be able to take a pointer to the array, cast it to something like unsigned long long *, dereference it and shift the resulting integer, and store it back again.
BUT if that's the behaviour you want then you should be using an integer instead of a char[8] to begin with.
(If you could say more about what you're actually aiming to achieve, then more helpful answers may be possible.)
If you want to perform operations such as shifting / OR / XOR / AND / etc.. on arrays, you should perform it in a loop, you cannot perform it directly on the array.
/** Shift an array right.
* #param ar The array to shift.
* #param size The number of array elements.
* #param shift The number of bits to shift.
*/
void shift_right(unsigned char *ar, int size, int shift)
{
int carry = 0; // Clear the initial carry bit.
while (shift--) { // For each bit to shift ...
for (int i = size - 1; i >= 0; --i) { // For each element of the array from high to low ...
int next = (ar[i] & 1) ? 0x80 : 0; // ... if the low bit is set, set the carry bit.
ar[i] = carry | (ar[i] >> 1); // Shift the element one bit left and addthe old carry.
carry = next; // Remember the old carry for next time.
}
}
}
You can shift only members of that arrays, a char (or an int). You can't shift an entire array. Shifting my_array tries to perform a shift operation on an array type (or a pointer to char) which is impossible. Do this instead:
for (i = 0; i < size; i++) {
my_array[i] >>= 1;
}
Also you must be careful with chars because they are usually signed, and a char containing a negative value will bring '1' from the left instead of zeros. So you better use unsigned chars.
EDIT:
The code above is simplistic. If you intended to shift right the array as a whole, not just each byte on its own, then you need to "manually" copy each LSB to the MSB of the byte to its right. Take a loop at the answer of Richard Pennington.
/**
* shift a number of bits to the right
*
* #param SRC the array to shift
* #param len the length of the array
* #param shift the number of consecutive bits to shift
*
*/
static void shift_bits_right(uint8_t SRC[], uint16_t len, uint32_t shift) {
uint32_t i = 0;
uint8_t start = shift / 8;
uint8_t rest = shift % 8;
uint8_t previous = 0;
for(i = 0; i < len; i++) {
if(start <= i) {
previous = SRC[i - start];
}
uint8_t value = (previous << (8 - rest)) | SRC[i + start] >> rest;
SRC[i + start] = value;
}
}
I know this is old topic but i was not satisfied with the answers available, here is something i wrote recently which allows you to specify the amount of bits you can shift by and also there is simple XOR encryption in it.
//https://github.com/ashvin-bhuttoo/CryptoTest/blob/master/CryptoTest/Crypto.cpp
//CRYPTO CONFIGURATION PARAMETERS
#define BIT_SHIFT 3
#define XOR_KEY 0x3C
#define ENABLE_XOR_VARIANCE true
////////////////////////////////
int get_rs_mask(int shift)
{
switch (shift)
{
case 0:
return 0x00;
case 1:
return 0x01;
case 2:
return 0x03;
case 3:
return 0x07;
case 4:
return 0x0F;
case 5:
return 0x1F;
case 6:
return 0x3F;
case 7:
return 0x7F;
default:
throw "get_rs_mask -> Error, shift argument outside legal range 0-7";
}
}
void shift_right(char* buf, int msg_len, int shift)
{
unsigned char tmp = 0x00, tmp2 = 0x00;
for (int k = 0; k <= msg_len; k++)
{
if (k == 0)
{
tmp = buf[k];
buf[k] >>= shift;
}
else
{
tmp2 = buf[k];
buf[k] >>= shift;
buf[k] |= ((tmp & get_rs_mask(shift)) << (8 - shift));
if (k != msg_len)
tmp = tmp2;
}
}
}
int get_ls_mask(int shift)
{
switch (shift)
{
case 0:
return 0x00;
case 1:
return 0x80;
case 2:
return 0xC0;
case 3:
return 0xE0;
case 4:
return 0xF0;
case 5:
return 0xF8;
case 6:
return 0xFC;
case 7:
return 0xFE;
default:
throw "get_ls_mask -> Error, shift argument outside legal range 0-7";
}
}
void shift_left(char* buf, int msg_len, int shift)
{
char tmp = 0x00, tmp2 = 0x00;
for (int k = msg_len; k >= 0; k--)
{
if (k == msg_len)
{
tmp = buf[k];
buf[k] <<= shift;
}
else
{
tmp2 = buf[k];
buf[k] <<= shift;
buf[k] |= ((tmp & get_ls_mask(shift)) >> (8 - shift));
tmp = tmp2;
}
}
}
void crypt(char* buf, int msg_len, bool decrypt = false)
{
if (!decrypt)
{
shift_right(buf, msg_len, BIT_SHIFT);
for (int k = 0; k < msg_len; k++)
{
buf[k] = buf[k] ^ XOR_KEY ^ k * (ENABLE_XOR_VARIANCE ? 2 : 0);
}
buf[msg_len] = '\0';
}
else
{
for (int k = 0; k < msg_len; k++)
{
buf[k] = buf[k] ^ XOR_KEY ^ k * (ENABLE_XOR_VARIANCE ? 2 : 0);
}
shift_left(buf, (msg_len)-1, BIT_SHIFT);
}
}
/**
* Shift a number of bits to the right
*
* #param array The array to shift
* #param len The length of the array
* #param shift The number of consecutive bits to shift. To the right if shift is positif.
*
*/
static void shift_bits_right(uint8_t *array, int len, int shift) {
uint8_t macro_shift = shift / 8;
shift = shift % 8;
uint8_t array_out[len];
memset(array_out, 0, len);
for(int i = 0; i < len; i++) {
if(i+macro_shift < len)
array_out[i+macro_shift] += array[i]>>shift;
if(i+macro_shift+1 < len)
array_out[i+macro_shift+1] += array[i]<<(8-shift);
}
memcpy(array, array_out, len);
}
For everyone who is looking for a code snippet to (logically) shift right a byte array that actually works:
template<size_t N> void shift_right(array<uint8_t, N>& arr, uint64_t bits)
{
int64_t num_bytes = bits / 8;
int64_t num_bits = bits % 8;
for(int64_t i = N-1; i >= 0; i--)
{
int64_t i_from = i - num_bytes;
int64_t i_from_minus_one = i - num_bytes - 1;
uint8_t v_from = i_from < 0 ? 0 : arr[i_from];
uint8_t v_from_minus_one = i_from_minus_one < 0 ? 0 : arr[i_from_minus_one];
arr[i] = v_from >> num_bits | v_from_minus_one << (8 - num_bits);
}
}
#include <stdio.h>
int main()
{
int num, i = 0,pos;
printf(" Enter num \n");
scanf("%d",&num);
for( i = 0; i < 31; i++ )
{
pos = 1 << i;
if ( num & pos )
printf("1");
else
printf("0");
}
printf("\n");
return 0;
}
/*
O/P
Enter Num
12
0011000000000000
*/
But i want to print the o/p as 0000000000001100
So, What are the changes i have to made to get the desired o/p
You're printing the least significant bit first. Change your for loop to count down:
for (int i = 31; i >= 0; i--)
EDIT:
Seem that I'm the one who overlooked desired output. So the solutions provided by others will work for the OP.
I'm surprised people overlooked the fact that endianness usually applies to byte level instead of bit, which make the plain index-based loop fail to provide required output.
for a decimal to big-endian byte, you need :
while (num)
{
big <<= 8;
big |= num & 0xFF;
num >>= 8;
}
so in order to output little-endian integer into big-endian binaries, you need :
// 'num' was 4-byte (int) data in little-endian format
while (num)
{
// select required byte block
unsigned char curByte = num & 0xFF;
// prints the byte binaries
for(int iBit=7; iBit>=0; --iBit)
{
unsigned char theBit = curByte >> iBit;
if (theBit & 0x1)
putchar('1');
else
putchar('0');
}
// shifts to next byte block
num >>= 8;
}
Change your for loop to be more like:
#define BIT(x) (1U << (x))
for (i = 31; i >= 0; --i)
{
if (x & BIT(i)) {
putchar('1');
}
else {
putchar('0');
}
}
I'm trying to simply convert a byte received from fget into binary.
I know the value of the first byte was 49 based on printing the value. I now need to convert this into its binary value.
unsigned char byte = 49;// Read from file
unsigned char mask = 1; // Bit mask
unsigned char bits[8];
// Extract the bits
for (int i = 0; i < 8; i++) {
// Mask each bit in the byte and store it
bits[i] = byte & (mask << i);
}
// For debug purposes, lets print the received data
for (int i = 0; i < 8; i++) {
printf("Bit: %d\n",bits[i]);
}
This will print:
Bit: 1
Bit: 0
Bit: 0
Bit: 0
Bit: 16
Bit: 32
Bit: 0
Bit: 0
Press any key to continue . . .
Clearly, this is not a binary value. Any help?
The problem you're having is that your assignment isn't resulting in a true or false value.
bits[i] = byte & (mask << i);
This gets the value of the bit. You need to see if the bit is on or off, like this:
bits[i] = (byte & (mask << i)) != 0;
Change
bits[i] = byte & (mask << i);
to
bits[i] = (byte >> i) & mask;
or
bits[i] = (byte >> i) & 1;
or
bits[i] = byte & 1;
byte >>= 1;
One way, among many:
#include <stdio.h>
#include <limits.h>
int main(void) {
int i;
char bits[CHAR_BIT + 1];
unsigned char value = 47;
for (i = CHAR_BIT - 1; i >= 0; i -= 1) {
bits[i] = '0' + (value & 0x01);
value >>= 1;
}
bits[CHAR_BIT] = 0;
puts(bits);
return 0;
}
You may notice that your output has a couple 1's and 0's, but also powers of 2, such as 32. This is because after you isolate the bit you want using the mask, you still have to bit-shift it into the least-significant digit so that it shows up as a 1. Or you could use what other posts suggested, and instead of bit-shifting the result (something like 00001000 for example), you could simply use (result != 0) to fetch either a 1 or 0, since in C, false is 0, and comparisons such as != will return 1 as true (I think).
#include<Stdio.h>
#include <limits.h>
void main(void) {
unsigned char byte = 49;// Read from file
unsigned char mask = 1; // Bit mask
unsigned char bits[8];
int i, j = CHAR_BIT-1;
// Extract the bits
for ( i = 0; i < 8; i++,j--,mask = 1) {
// Mask each bit in the byte and store it
bits[i] =( byte & (mask<<=j)) != NULL;
}
// For debug purposes, lets print the received data
for (int i = 0; i < 8; i++) {
printf("%d", bits[i]);
}
puts("");
}
This addition in place of that will work:
bits[i]= byte & (mask << i);
bits[i] >>=i;