Why is bitwise OR operation not working as expected when an unsigned char is ORed with 11100000? - c

I am not able to understand why the operation 'c | 11100000' does not seem to work. But I also noticed that 'c | 10000000' works as expected.
#include <stdio.h>
int main()
{
unsigned char c, c1;
c = c & 0;
c = c | 11100000;
printf("%o \t", c);
/** prints 140 ***/
c = c & 0;
c = c | 111;
c << 5;
printf("%o", c);
/** prints 157 **/
return 0;
}

The constant values that you are using are in decimal format, not binary.
C doesn't support binary constants, but it does support hex constants:
c = c | 0xe0;
...
c = c | 0x7;
Also, this doesn't do anything:
c << 5;
Presumably, you want:
c = c << 5;

The problem of the confusion is that you think that this integer constant 11100000 represents a binary literal. That is 1 and 0 are bit values.
However if you will execute this statement
printf( "11100000 = %x\n", 11100000 );
you will see that the hexadecimal representation of the constant is a95f60
11100000 = a95f60
So in this statement
c = c | 11100000;
the less significant byte that is equal to 0x60 (or in decimal 96) is assigned to the variable c.
It is not the same if to write
c = c | 111;
c <<= 5;
Moreover pay attention to that this expression statement
c << 5;
does not have an effect. It seems you mean
c <<= 5;
that is equivalent to the multiplication of the decimal value 111 by 32 and again assigning the less significant byte to the variable c.
If you will execute this statement
printf( "111 << 5 = %d\n", 111 << 5 );
then you will see that the result is
111 << 5 = 3552
As it is seen 3552 is not the same as 11100000.
So the output of this statement
c = 111 << 5;
printf( "%d\n", c);
is decimal 224.
Opposite to C++ in C there are no integer binary constants.
In C++ there are binary literals and you could obtain the expected result running this program
#include <cstdio.h>
int main()
{
unsigned char c = 0;
c = c | 0b11'100'000;
printf( "%o\t", c );
c = 0b111;
c <<= 5;
printf( "%o\n", c );
}
The program output is
340 340

Related

Is there a way to manipulate the bits that I shift in C

If I have an int a, which is lets say equal to 0.
Is there a way for me to say left shift 101 into the variable and then in another step shift in 011 into it? Then I could get the int decimal number at the end? It would end up becoming 0b00000000000000000000000000101011.Or should I only use the OR operation.
You can't shift bits into the variable; you can OR them in:
int a = 0;
a |= 5;
printf("a = %d\n", a);
a <<= 3;
a |= 3;
printf("a = %d\n", a);
If your system supports binary constants, you can use those instead of decimals (and you can prefix 5 and 3 with 0 for octal or 0x for hexadecimal if you prefer — and you can print with a different format according to taste, too). If the starting value for a isn't known to be 0, you would do a shift-assignment operation before the first |= operation.
Eventually, you have to worry about left-shifting a signed integer value such that overflow occurs — that leads to undefined behaviour. It isn't a problem with the values in the question, though.
You would need to first shift by the required number of bits then perform a bitwise OR of the new data.
int a = 0;
a = a << 3;
a = a | 0x5;
a = a << 3;
a = a | 0x3;
printf("a=%x\n", a);
( Used separate assignments and operators instead of compound operators to make it clearer to beginners. )
Result:
a=2b
Is there a way for me to say left shift 101 into the variable
No. You need to left shift first, then add (or OR) the new value.
int eax = 0;
eax <<= 3;
eax |= 5;
int a = 0;
a << 3;
a |= 0x5;
a << 3;
a |= 0x3;
There isn't a predefined way to "shift in" a value like that. It wouldn't take much time to write a function that could though.
There is - to my knowledge - no operation that "shifts" a number of bits from one integer into another. The left shift operator always fills the arising spaces with 0, such that you have to combine it with, for example, an |-operation (actually a + would have the same effect in your case).
#include <stdio.h>
void printBinary(int b, int nrOfBits) {
for (int mask = (1 << nrOfBits); mask != 0; mask >>=1 ) {
char c = (b & mask) ? '1' : '0';
printf("%c", c);
}
}
int main()
{
int a = 0;
a = (a << 3) | 0x5;
printBinary(a, 8);printf("\n");
a = (a << 3) | 0x3;
printBinary(a, 8);printf("\n");
return 0;
}
When using left shift operators on signed datatypes be careful not to produce undefined behaviour (cf. cppreference concerting arithmetic operations):
When signed integer arithmetic operation overflows (the result does
not fit in the result type), the behavior is undefined

K&R Exercise 2-7, optimisations?

I'm currently learning C with "The C Programming Language" from K&R. I solved the exercise 2-7, which says:
Write a function invert(x,p,n) that returns x with the n bits that begin at position p inverted (i.e., 1 changed into 0 and vice versa), leaving the other bits unchanged.
Here is my code (I voluntarily used chars here):
#include <stdio.h>
#define NUMBER 235
#define POSITION 2
#define AMOUNT 4
unsigned invert(unsigned char x, char p, char n)
{
unsigned char bitsToInvert = 0, i;
for (i = 1; i < n; i++) { // Make a number n-bits width, full of 1
bitsToInvert |= 1;
bitsToInvert <<= 1;
}
bitsToInvert |= 1;
bitsToInvert <<= p;
x ^= bitsToInvert;
return x;
}
int main()
{
printf("%d\n", invert(NUMBER, POSITION, AMOUNT));
}
Is there any optimisation I could bring to my code? Especially on the for loop which create a number of n 1 bits?
Thanks!
2^n - 1 is always a number with all n LSB bits set.
For eg:
2 ^ 3 - 1 = 7 => 111
2 ^ 5 - 1 = 31 => 11111
In your case, you can do away with the for loop to construct this number by simply saying:
bitsToConvert = (1<<n) - 1;
Dont forget to take care of extreme situations.
An alternative to what Thrustmaster said, that would work for any "n" without the need for specifying it, would be using a bitwise not on an empty value.
variable = ~(variable ^ variable);

right shift operator on hexadecimal in turbo c++

#include<stdio.h>
#include<conio.h>
void main()
{
int x=0x01c0ffee;
int y=x>>15+1&0xff;
clrscr();
printf("%x ",y);
getch();
}
the following code prints ff in turbo c++ and instead of
15+1
if we use
7+1
returns the same answer ff.
so, does turbo c++ considers x>> 8 and x>>16 same on hexa,something like that?
To debug your code, I would suggest breaking down the output into the individual operations, but also check that you have enough room in your variables.
#include<stdio.h>
void main()
{
int x = 0x01c0ffee;
int y = x >> 15 + 1 & 0xff;
printf("Size: %d\n", sizeof(int));
printf("1.) %x\n", x);
printf("2.) %x\n", x >> 15);
printf("3.) %x\n", x >> 15 + 1);
printf("4.) %x\n", x >> 15 + 1 & 0xFF);
printf("Final: %x\n",y);
}
The output of Size: will show you how many bytes you have for int. You need one byte for every two hexademical digit.
Here is the output on my 32-bit machine:
Size: 4
1.) 1c0ffee
2.) 381
3.) 1c0
4.) c0
Final: c0
If you see Size: 2, then there's your problem. Try using long int.
Also, I would recommend using unsigned if you're performing shift operations since the behavior of right-shift on signed variables is implementation-specific (which means Turbo C could act different from gcc)

Convert binary to hex to decimal

I have the binary number 1010 1011. I know that this is AB in hex and I know that A = 10 and B = 11 in decimal. But how do I get from 10 and 11 in decimal to the final number of 171?
With hex I would do
A B
0xAB = (10 * 16^1) + (11 * 16^0) = 171
Can I do something similar with the decimal numbers to go from 10 and 11 to 171? Basically, I'm just looking for a fast way to convert any binary number without a calculator.
I don't think there's a much easier way than A × 16 + B.
Depending on what you are trying to do, and the the language you are using, you could use the shift-left operator and add the values together.
In C++:
unsigned short val_a = (0x1010 << 4);
unsigned short val_b = 0x1011;
unsigned short result = val_a + val_b;
The result is still an unsigned short int.
In C you can shift instead if multiplication to get AB from A and B:
int number = A << 4 + B;
if you store A as 1010 (decimal) and B as 1011, you can convert:
int bin2dec(unsigned int s){
int v, p;
for (v = 0, p = 1; s > 0; s=s>>1) { v = v+p*(s%2); v++; p*=2;}
return v;
}
int number = bin2dec(A) << 4 + bin2dec(B);

OR operator in C not working

I don't understand why the final printf in the code below is not printing 255.
char c;
c = c & 0;
printf("The value of c is %d", (int)c);
int j = 255;
c = (c | j);
printf("The value of c is %d", (int)c);
In most implementations the char type is signed, so it ranges from -128 to 127.
This means, 11111111 (which is 255 written in binary) is equal to -1. (As it's represented as a value stored in two's complement)
To get what you expect, you need to declare c as a unsigned char, like so:
unsigned char c = 0;
int j = 255;
c = (c | j);
printf("The value of c is %d", (int)c);
It is probably printing -1. That is because
c = (c | j);
will evaluate as
c = (0 | 255) = (0 | 0xFF) = 0xFF
but, since c is signed, 0xFF will be -1 and not 255 as you expected. If you change c to unsigned char it will print 255, as you imagined.
Try to replace char c with unsigned char c. Basically char type supports values from -128 to 127. Your result is bigger than the supported range and overflows.
By default char
is signed char
in C. If you want 255 to be printed then use unsigned char
however i explain the output in context of signed char
so that the concept becomes clear.
If you write j=127 then it will print 127 as the bit representation is 01111111.
But if you write j=128
then it will print -128
because the bit representation 01111111 has increased by 1 to become 10000000.
now if you write j=255
then the bit representation is 11111111. so it will print -1
If you write j=256
then it will print 0
because when bit representation 11111111 is increased by 1 it becomes 100000000. But only 1 byte is allocated for a characher variable so the left most bit is not stored and bit representation becomes 00000000.
Further if you write j=257
then its also a case of overflow and the bit representation become 00000001 and 1 will be printed.

Resources