C decimal to binary converter (16 bits) - c

I'm trying to convert a decimal number into binary (16 bits max). My function works perfectly for up to 8 bits but when I want to print numbers up to 16 bits, it stop printing characters.
I used "int" as my data type for 8 bits but since I want to store 16 bits I'm using an unsigned long int in every variable.
Here's the code:
/* Program to convert decimal to binary (16 bits) */
#include <stdio.h>
#include <string.h>
char *byte_to_binary_str(long unsigned int byte);
int main()
{
printf("%s",byte_to_binary_str(32768)); //1000000 0000000
return 0;
}
char *byte_to_binary_str(long unsigned int byte)
{
static char bit_string[17];
bit_string[0] = '\0';
long unsigned int mask;
for (mask = 2^15; mask > 0; mask >>= 1) {
/* Check if the mask bit is set */
strcat(bit_string, byte & mask ? "1" : "0");
}
return bit_string;
}
My output gives me:
0000
Process returned 0 (0x0) execution time : 0.063 s
Press any key to continue.
Anyone know why is this happening? Thanks in advance.

mask = 2^15;
does not set the value of mask to what you are expecting 2^15 is no 2 raised to the power 15. It is bitwise XOR of 2 and 15.
You need something that is 1000 0000 0000 0000 in binary. That number will be 0x8000 in hex. Hence, use:
mask = 0x8000;
You can also use something that makes sense in your algorithm.
mask = 1u << 15;

Related

Test feedback: oddParitySet3 incorrectly returned

Purpose: Demonstrate the ability to manipulate bits using functions and to learn a little bit about parity bits.
Parity is a type of error detection where one of the bits in a bit string is used for this purpose. There are more complicated systems that can do more robust error detection as well as error correction. In this lab, we will use a simple version called odd parity. This reserves one bit as a parity bit. The other bits are examined, and the parity bit is set so that the number of 1 bits is odd. For example, if you have a 3-bit sequence, 110 and the rightmost bit is the parity bit, it would be set to 1 to make the number of 1s odd.
Notes: When referring to bit positions, bit 31 is the high-order bit (leftmost), and bit 0 is the low-order bit (rightmost). In order to work through these functions, you will likely have to map out bit patterns for testing to see how it all works. You may find using a converter that can convert between binary, hex, and decimal useful. Also, to assign bit patterns to integers, it might be easier to use hex notation. To assign a hex value in C, you can use the 0x????? where ????? are hex values. (There can be more or fewer than the number of ? here.) E.g.,
int i = 0x02A;
Would assign i = 42 in decimal.
Program Specifications: Write the functions below:
unsigned int leftRotate(unsigned int intArg, unsigned int rotAmt);
Returns an unsigned int that is intArg rotated left by rotAmt. Note: Rotate left is similar to shift left. The difference is that the bits shifted out at the left come back in on the right. Rotate is a common operation and often is a single machine instruction. Do not convert intArg to a string and operate on that. Do not use an array of ints (or other numbers). Use only integers or unsigned integers.
Example: Assuming you have 5-bit numbers, rotating the binary number 11000 left by 3 yields 00110
char *bitString(int intArg)
Returns a pointer to a character string containing the 32-bit pattern for the integer argument. The first character, index 0, should be the high-order bit and on down from there. For this function, you will need malloc. Can be used for printing bit patterns. E.g., if intArg = 24 the return string would be 00000000000000000000000000011000
unsigned int oddParitySet3(unsigned int intArg, unsigned int startBit);
This function will determine the odd parity for a 3-bit segment of intArg starting at bit startBit and set the parity bit (low-order bit) appropriately.
E.g., suppose intArg=3 and startBit = 2. The 32 bit representation, from high to low, would be 29 zeros then 110. So, bits 2 - 0 are 011. To make the parity odd, you would set bit zero to 0.
The return value is the modified intArg, in this case it would be 29 zeros then 010 or a value of 2.
Do not convert intArg to a string and operate on that. Use only integers or unsigned integers.
Note: If the start bit is greater than 31 or less than 2, this would present a problem (do you see this?). If this is the case, return a zero.
The compile command used by this zyLab is:
gcc main.c -Wall -Werror -Wextra -Wuninitialized -pedantic-errors -o a.out -lm
The program does not pass all tests and gives such errors:
enter image description here
C code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char * bitString(int intArg);
unsigned int leftRotate(unsigned int n, unsigned int d);
unsigned int oddParitySet3(unsigned int intArg, unsigned int startBit);
int main() {
return 0;
}
char * bitString(int intArg)
{
char *bits = (char*)malloc(33 * sizeof(char));
bits[32] = '\0';
for(int i = 31; i >= 0; i--)
{
if(intArg & (1 << i))
bits[31 - i] = '1';
else
bits[31 - i] = '0';
}
return bits;
}
unsigned int leftRotate(unsigned int intArg, unsigned int rotAmt)
{
return (intArg << rotAmt) | (intArg >> (32 - rotAmt));
}
unsigned int oddParitySet3(unsigned int intArg, unsigned int startBit){
unsigned int mask = 0x00000007;
unsigned int shiftedMask = mask << startBit;
unsigned int temp = intArg & shiftedMask;
unsigned int result = intArg;
if(__builtin_popcount(temp) % 2 == 0)
result |= shiftedMask;
else
result &= ~shiftedMask;
return result;
}
need help to fix the oddParitySet3 function so that it does not display errors that are in the photo.

Am I using memcpy wrong?

I'm trying to use memcpy to copy part of an unsigned int to another unsigned int within the same struct I made. But my program only prints the first printf statement and then says: Process returned -1073741819 (0xC0000005)
Am I using memcpy wrong?
#include <stdio.h>
#include <string.h>
int main()
{
struct time
{
unsigned int hours:5;
unsigned int minutes:6;
unsigned int seconds:6;
};
struct time t = {0x10,0b101011,45};
printf("The time is : %d:%d:%d\n", t.hours, t.minutes, t.seconds);
memcpy(t.minutes, t.seconds, 2);
printf("The time is : %d:%d:%d\n", t.hours, t.minutes, t.seconds);
return 0;
}
I've already done t.minutes = t.seconds and that copies the whole number, but I only want a portion of it.
In response to your clarification in the comments:
When I say part of number I mean I'm trying to copy the most significant 2 bits of the unsigned int.
The way to copy individual bits is by doing bit manipulation with bitwise operators.
The two most significant bits in your 6-bit fields are therefore represented by the value 0x30 (110000 in binary). To copy these from one to another, simply clear out those bits in the destination, then mask the source and combine with bitwise-OR:
unsigned int mask = 0x30;
t.minutes = (t.minutes & ~mask) | (t.seconds & mask);
Breakdown of the above:
~mask inverts the mask, meaning that bits 4 and 5 will be 0 and all other bits will be 1
this value is then ANDed with minutes, resulting in clearing bits 4 and 5
the opposite occurs when ANDing the mask with seconds, resulting in only bits 4 and 5 being preseved, and all other bits cleared
the two values are then combined with OR and assigned to minutes

How to cast 10 bit sign integer to 16 bit integer in C

I am parsing a data which is a 10 bit signed integer. Since the only way to represent this data is to either use int or short ( for sign 2-byte representation), I have to cast 10 bit to 16 bit.
I have applied 2 methods already but they are either slow or compiler depended.
The slow method is to use pow() function
value = pow(2,16) - pow(2,10) + value
The compiler dependent method is
value = (value << 6) >> 6 (right shift shifts the MSB which is a compiler dependent operation and may shift 0 if compiler is different)
Can someone help me find the standar way of casting non standard types to standard types
Here is the logic for the operations explicitly written out. Obviously you can do this with a one-liner, but I hope this explains why.
#include <stdio.h>
#include <string.h>
#include <stdint.h>
int main(int argc, char* argv[]) {
//int16_t value = 0x3fdb; // random examples
//int16_t value = 0x00f3;
int16_t value = 0x3f3;
printf("0x%04x (%i)\n", value, value); // in
uint16_t mask = 0x3ff; // 0000 0011 1111 1111 in binary
uint16_t masked = value & mask; // get only the 10 LSB
uint16_t extension = (0x200 & value) ? 0xFC00 : 0x0; // extend with 1s or 0s
printf("extension: %i\n", (extension)?1:0);
int16_t extended = extension | masked; // do the extension
printf("0x%04x (%i)\n", extended, extended); // out
return 0;
}
Examples:
0x00f3 (243)
extension: 0
0x00f3 (243)
0x3fdb (16347)
extension: 1
0xffffffdb (-37)
0xfffffff3 (-13)
extension: 1
0xfffffff3 (-13)
0x03f3 (1011)
extension: 1
0xfffffff3 (-13)
value = value & 0x03FF; //mask off the high 6 bits like you want.
There should be no 10 bit integers, i assume value is a short but you should add that relevant info.
edit
If you only want to mask if the 10th bit is set then:
value = (value & 0x0200) ? (value & 0x03FF) : value;

How do I extract bits from 32 bit number

I have do not have much knowledge of C and I'm stuck with a problem since one of my colleague is on leave.
I have a 32 bit number and i have to extract bits from it. I did go through a few threads but I'm still not clear how to do so. I would be highly obliged if someone can help me.
Here is an example of what I need to do:
Assume hex number = 0xD7448EAB.
In binary = 1101 0111 0100 0100 1000 1110 1010 1011.
I need to extract the 16 bits, and output that value. I want bits 10 through 25.
The lower 10 bits (Decimal) are ignored. i.e., 10 1010 1011 are ignored.
And the upper 6 bits (Overflow) are ignored. i.e. 1101 01 are ignored.
The remaining 16 bits of data needs to be the output which is 11 0100 0100 1000 11 (numbers in italics are needed as the output).
This was an example but I will keep getting different hex numbers all the time and I need to extract the same bits as I explained.
How do I solve this?
Thank you.
For this example you would output 1101 0001 0010 0011, which is 0xD123, or 53,539 decimal.
You need masks to get the bits you want. Masks are numbers that you can use to sift through bits in the manner you want (keep bits, delete/clear bits, modify numbers etc). What you need to know are the AND, OR, XOR, NOT, and shifting operations. For what you need, you'll only need a couple.
You know shifting: x << y moves bits from x *y positions to the left*.
How to get x bits set to 1 in order: (1 << x) - 1
How to get x bits set to 1, in order, starting from y to y + x: ((1 << x) -1) << y
The above is your mask for the bits you need. So for example if you want 16 bits of 0xD7448EAB, from 10 to 25, you'll need the above, for x = 16 and y = 10.
And now to get the bits you want, just AND your number 0xD7448EAB with the mask above and you'll get the masked 0xD7448EAB with only the bits you want. Later, if you want to go through each one, you'll need to shift your result by 10 to the right and process each bit at a time (at position 0).
The answer may be a bit longer, but it's better design than just hard coding with 0xff or whatever.
OK, here's how I wrote it:
#include <stdint.h>
#include <stdio.h>
main() {
uint32_t in = 0xd7448eab;
uint16_t out = 0;
out = in >> 10; // Shift right 10 bits
out &= 0xffff; // Only lower 16 bits
printf("%x\n",out);
}
The in >> 10 shifts the number right 10 bits; the & 0xffff discards all bits except the lower 16 bits.
I want bits 10 through 25.
You can do this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number & 0x3FFFC00) >> 10;
Or this:
unsigned int number = 0xD7448EAB;
unsigned int value = (number >> 10) & 0xFFFF;
I combined the top 2 answers above to write a C program that extracts the bits for any range of bits (not just 10 through 25) of a 32-bit unsigned int. The way the function works is that it returns bits lo to hi (inclusive) of num.
#include <stdio.h>
#include <stdint.h>
unsigned extract(unsigned num, unsigned hi, unsigned lo) {
uint32_t range = (hi - lo + 1); //number of bits to be extracted
//shifting a number by the number of bits it has produces inconsistent
//results across machines so we need a special case for extract(num, 31, 0)
if(range == 32)
return num;
uint32_t result = 0;
//following the rule above, ((1 << x) - 1) << y) makes the mask:
uint32_t mask = ((1 << range) -1) << lo;
//AND num and mask to get only the bits in our range
result = num & mask;
result = result >> lo; //gets rid of trailing 0s
return result;
}
int main() {
unsigned int num = 0xd7448eab;
printf("0x%x\n", extract(num, 10, 25));
}

Left Bit Shift In C without extension

I was wondering how to get C to not extend my binary number when I bitshift to the left
int main ()
{
unsigned int binary_temp = 0b0100;
binary_temp = binary_temp << 2;
printf("%d", binary_temp);
return 0;
}
When I run that I want a return value of 0 since it has extended past the 4 digits I have, but right now it returns 16 (10000). How would I get C not to extend my number?
Edit: I would like to be able to work with the number in binary form so I need to have only 4 digits, and not just outputting the right number.
It does not extend your number but saves it as unsigned int type which is 4 bytes (32 bits) in size. You only fill the last 4 bits. To treat it as only 4 bits, use Bitwise AND with a Mask value. Here's example code:
int main()
{
unsigned int binary_temp = 0b0100;
binary_temp = (binary_temp << 2) & 0b1111;
printf("%u", binary_temp);
return 0;
}
You can bitwise AND the result with a 4 bit mask value:
binary_temp = (binary_temp << 2) & 0xF;
There is no 0b in standard C. You could use 4.
unsigned int /* prepare for wtf identifier: */
binary_temp = 4;
Left shifting by 2 is multiplying by 4. Why not?
binary_temp *= 4;
... and then reduce modulo 16?
binary_temp %= 16;
What sense is there to using binary operators, in this case? I see none.
The %d directive corresponds to an int argument, but the argument you're giving printf is an unsigned int. That's undefined behaviour.
printf("%u", binary_temp);
I'm sure whichever book you're reading will tell you about the %u directive.

Resources