What is the signification of ~ and & binary operator in C [duplicate] - c

This question already has answers here:
How does the bitwise complement operator (~ tilde) work?
(18 answers)
Closed 3 years ago.
I recently had to use the sbrk() function in c
and i had to calcul the size that i'll use for allocate spaces in memory.
After some researches i found this line of code:
size_t calc_size = ((size) + ((4096) - 1)) & ~((4096) - 1);
Despite my searches for understand what the operators "~" and "&" means, i have a mean level in c and i could not find clear explanations, precisely for the ~ operator. Could you help me to understand what operation is being performed ?

Despite my searches for understand what the operators "~" and "&" means,
Those are bitwise NOT and bitwise AND operators, respectively. They differ from logical NOT (!) and logical AND (&&) in that they work on each individual bit (hence the name). There are also bitwise OR (|) and XOR (^) operators. Examples:
int a = 0x5A; // a = 01011010
int b = ~a; // b = 10100101, i.e. bits of a inverted
int c = a & b; // c = 00000000, i.e. bits of a and b ANDed together
int d = a | b; // d = 11111111, i.e. bits of a and b ORed together
int e = a ^ 0x3D; // e = 01100110, i.e. bits of a XORed with 00111100
Could you help me to understand what operation is being performed ?
The code is converting size into a multiple of 4096. The sbrk() function adjusts the amount of memory allocated to a process, and 4 kilobytes is a typical virtual memory page size, so it makes sense to increase memory in 4K increments. The idea here seems to be to add 4095 to the requested size, so that even a 1-byte request will be promoted to a whole 4096-byte block, and then eliminate the low bits so that you get a multiple of 4K. To understand this better, plug in some different values for size and look at what you get for calc_size.

~ is the bitwise NOT operator. It inverts all bits in its operand.
As for what it means in the context of this expression:
size_t calc_size = ((size) + ((4096) - 1)) & ~((4096) - 1);
This rounds up size to the nearest multiple of 4096.
First lets look at ~((4096) - 1) using binary representation. 4096 is:
0001000000000000
(For simplicity's sake I'll just show the lowest 16 bits. Any higher order bits will be the same as the leftmost). Now subtract 1:
0000111111111111
And apply ~:
1111000000000000
This value is then used as a bitmask which clears the lowest order 12 bits, i.e. the result will be a multiple of 4096.
After that, 4095 is added to size. If it is already a multiple of 4096, this results in only the low order 12 bits being set which the mask will remove. If it is not, then the addition will carry into the 13th bit, rounding it up, and the mask again removes the lower bits.

& is the AND bitwise operator. It works like this:
0101
0011
= 0001
It is the same logic of the && but it's a bit by bit operation.
~ is the NOT bitwise operator, the same way:
0111
= 1000

Related

what the meaning of (a&b)>>c in this systemc code? [duplicate]

This question already has answers here:
What are bitwise operators?
(9 answers)
Closed last month.
when I read SYSTEMC code,I find a function return int like this:
static inline int rp_get_busaccess_response(struct rp_pkt *pkt)
{
return (pkt->busaccess_ext_base.attributes & RP_BUS_RESP_MASK) >>
RP_BUS_RESP_SHIFT;
}
pkt->busaccess_ext_base.attributes defined as uint64_t.
RP_BUS_RESP_MASK and RP_BUS_RESP_SHIFT defined as:
enum {
RP_RESP_OK = 0x0,
RP_RESP_BUS_GENERIC_ERROR = 0x1,
RP_RESP_ADDR_ERROR = 0x2,
RP_RESP_MAX = 0xF,
};
enum {
RP_BUS_RESP_SHIFT = 8,
RP_BUS_RESP_MASK = (RP_RESP_MAX << RP_BUS_RESP_SHIFT),
};
What the meaning of this function's return?
Thanks!
a & b is a bitwise operation, this will perform a logical AND to each pair of bits, let's say you have 262 & 261 this will translate to 100000110 & 100000101 the result will be 100000100 (260), the logic behind the result is that each 1 AND 1 will result in 1 whereas 1 AND 0 and 0 AND 0 will result in 0, these are normal logical operations but are performed at bit level:
100000110
& 100000101
-----------
100000100
In (a & b) >> c, >> will shift the bits of the resulting value of a & b to the right by c positions. For example for the previous result 100000100 and having a c value of 8, all bits will shift to the right by 8, and the result is 000000001. The left most 1 bit in the original value will become the first most right whereas the third 1 bit from the right in the original value will be shifted away.
With this knowledge in mind and looking at the function, we can see that the RP_BUS_RESP_MASK constant is a mask that protects the field of bits from 9th through 12th position(from the right, i.e. the first four bits of the second byte), setting them to 1 (RP_RESP_MAX << RP_BUS_RESP_SHIFT which translates to 1111 << 8 resulting in 111100000000), this will preserve the bit values in that range. Then it sets the other bits of pkt->busaccess_ext_base.attributes to 0 when it performs the bitwise & against this mask. Finally it shifts this field to the right by RP_BUS_RESP_SHIFT(8).
It basically extracts the the first four bits in the second byte of kt->busaccess_ext_base.attributes and returns the result as an integer.
What it's for specifically? You must consult the documentation if it exists or try to understand its use in the global context, for what I can see this belongs to LibSystemCTLM-SoC (In case you didn't know)
The function extracts the first 4-Bit of the second byte of the 8-Byte (64-Bit) Attribute. This means, it extracts the following 4-Bits of the Attribute 0xFFFF FFFF FFFFF FAFF resulting in 0x0A
First it creates the mask, which is RP_BUS_RESP_MASK = 0x0F00
Next it applies the mask to the attribute pkt->busaccess_ext_base.attributes & 0x0F00 resulting in 0x0A00 from the example
Next it shifts A by 8-Bit to the right side, leading to 0x0A

Rotate bits in cryptography

I need explanation what exaclty means this operation in C language.
I know this is doing a bit shift to left by n, but I don't understand this code:
| (a >> (32 - n)).
This is full code below:
uint32_t rot_l(uint32_t a, uint8_t n)
{
return (a << n) | (a >> (32 - n));
}
Please help me understand this.
Given a sample 32 bit integer a:
11000000001111111110000000000000
a << n will shift the entire sequence to the left by n bits. Any bits that are shifted to the left of the first bit are removed. Any new bits added on the right are 0. So, say we shift this by n = 3, we'll get:
00000001111111110000000000000000
Then, a >> (32 - n) will shift a to the right by 32 - n. Note that 32 is the size in bits of a, so 32 - n will shift all the bits that didn't get truncated to the right. For n = 3 again, we'll get:
00000000000000000000000000000110
(the 110 is the first 3 most significant bits of n)
Finally, the | is the bitwise or operator, and this will compute the result of every using or on every bit in the two results.
00000001111111110000000000000000
00000000000000000000000000000110
================================ |
00000001111111110000000000000110
So what happens is, first the bits of a are shifted to the left by n. This results in the n most significant bits being truncated. Then these n most signifcant bits are shifted all the way to the right, to fill up the space that was originally filled with 0 from the left shift.
The result is then combined using the |. This simulates the entire string of bits in the integer being rotated to the left. This makes sense given the name of the function is rot_l :)

how do I perform shifts in c without losing bits?

In C when you do something like this:
char var = 1;
while(1)
{
var = var << 1;
}
In the 8th iteration the "<<" operator will shift out the 1 and var will be 0. I need to perform a shift in order to mantain the bit shifting. In other words I need this:
initial ----- 00000001
1st shift -- 00000010
2nd shift - 00000100
3rd shift - 00001000
4th shift - 00010000
5th shift -- 00100000
6th shift -- 01000000
7th shift - 10000000
8th shift - 00000001 (At the 8th shift the one automatically start again)
Is there something equivalent to "<<" but to achieve this?
This is known as a circular shift, but C doesn't offer this functionality at the language level.
You will either have to implement this yourself, or resort to inline assembler routines, assuming your platform natively has such an instruction.
For example:
var = (var << 1) | (var >> 7);
(This is not well-defined for negative signed types, though, so you'd have to change your example to unsigned char.)
Yes, you can use a circular shift. (Although it isn't a built-in C operation, but it is a CPU instruction on x86 CPUs)
So you want to do a bit rotation, a.k.a. circular shift, then.
#include <limits.h> // Needed for CHAR_BIT
// positive numbits -> right rotate, negative numbits -> left rotate
#define ROTATE(type, var, numbits) ((numbits) >= 0 ? \
(var) >> (numbits) | (var) << (CHAR_BIT * sizeof(type) - (numbits)) : \
(var) << -(numbits) | (var) >> (CHAR_BIT * sizeof(type) + (numbits)))
As sizeof() returns sizes as multiples of the size of char (sizeof(char) == 1), and CHAR_BIT indicates the number of bits in a char (which, while usually 8, won't necessarily be), CHAR_BIT * sizeof(x) will give you the size of x in bits.
This is called a circular shift. There are intel x86 assembly instructions to do this but unless performance is REALLY REALLY A HUGE ISSUE you're better off using something like this:
int i = 0x42;
int by = 13;
int shifted = i << by | i >> ((sizeof(int) * 8) - by);
If you find yourself really needing the performance, you can use inline assembly to use the instructions directly (probably. I've never needed it badly enough to try).
It's also important to note that if you're going to be shifting by more places than the size of your data type, you need additional checks to make sure you're not overshifting. Using by = 48 would probably result in shifted receiving a value of 0, though this behavior may be platform specific (i.e. something to avoid like the plague) because if I recall correctly, some platforms perform this masking automatically and others do not.

What does >> and 0xfffffff8 mean?

I was told that (i >> 3) is faster than (i/8) but I can't find any information on what >> is. Can anyone point me to a link that explains it?
The same person told me "int k = i/8, followed by k*8 is better accomplished by (i&0xfffffff8);" but again Google didn't help m...
Thanks for any links!
As explained here the >> operator is simply a bitwise shift of the bits of i. So shifting i 1 bit to the right results in an integer-division by 2 and shifting by 3 bits results in a division by 2^3=8.
But nowadays this optimization for division by a power of two should not really be done anymore, as compilers should be smart enough to do this themselves.
Similarly a bitwise AND with 0xFFFFFFF8 (1...1000, last 3 bits 0) is equal to rounding down i to the nearest multiple of 8 (like (i/8)*8 does), as it will zero the last 3 bits of i.
Bitwise shift right.
i >> 3 moves the i integer 3 places to the right [binary-way] - aka, divide by 2^3.
int x = i / 8 * 8:
1) i / 8, can be replaced with i >> 3 - bitwise shift to the right on to 3 digits (8 = 2^3)
2) i & xfffffff8 comparison with mask
For example you have:
i = 11111111
k (i/8) would be: 00011111
x (k * 8) would be: 11111000
Therefore the operation just resets last 3 bits:
And comparable time cost multiplication and division operation can be rewritten simple with
i & xfffffff8 - comparison with (... 11111000 mask)
They are Bitwise Operations
The >> operator is the bit shift operator. It takes the bit represented by the value and shifts them over a set number of slots to the right.
Regarding the first half:
>> is a bit-wise shift to the right.
So shifting a numeric value 3 bits to the right is the same as dividing by 8 and inting the result.
Here's a good reference for operators and their precedence: http://web.cs.mun.ca/~michael/c/op.html
The second part of your question involves the & operator, which is a bit-wise AND. The example is ANDing i and a number that leaves all bits set except for the 3 least significant ones. That is essentially the same thing happening when you have a number, divide it by 8, store the result as an integer, then multiply that result by 8.
The reason this is so is that dividing by 8 and storing as an integer is the same as bit-shifting to the right 3 places, and multiplying by 8 and storing the result in an int is the same as bit-shifting to the left 3 places.
So, if you're multiplying or dividing by a power of 2, such as 8, and you're going to accept the truncating of bits that happens when you store that result in an int, bit-shifting is faster, operationally. This is because the processor can skip the multiply/divide algorithm and just go straight to shifting bits, which involves few steps.
Bitwise shifting.
Suppose I have an 8 -bit integer, in binary
01000000
If I left shift (>> operator) 1 the result is
00100000
If I then right shift (<< operator) 1, I clearly get back to wear I started
01000000
It turns out that because the first binary integer is equivelant to
0*2^7 + 1*2^6 + 0*2^5 + 0*2^4 + 0*2^3 + 1*2^2 + 0*2^1 + 0*2^0
or simply 2^6 or 64
When we right shift 1 we get the following
0*2^7 + 0*2^6 + 1*2^5 + 0*2^4 + 0*2^3 + 1*2^2 + 0*2^1 + 0*2^0
or simply 2^5 or 32
Which means
i >> 1
is the same as
i / 2
If we shift once more (i >> 2), we effectively divide by 2 once again and get
i / 2 / 2
Which is really
i / 4
Not quite a mathematical proof, but you can see the following holds true
i >> n == i / (2^n)
That's called bit shifting, it's an operation on bits, for example, if you have a number on a binary base, let's say 8, it will be 1000, so
x = 1000;
y = x >> 1; //y = 100 = 4
z = x >> 3; //z = 1
Your shifting the bits in binary so for example:
1000 == 8
0100 == 4 (>> 1)
0010 == 2 (>> 2)
0001 == 1 (>> 3)
Being as you're using a base two system, you can take advantage with certain divisors (integers only!) and just bit-shift. On top of that, I believe most compilers know this and will do this for you.
As for the second part:
(i&0xfffffff8);
Say i = 16
0x00000010 & 0xfffffff8 == 16
(16 / 8) * 8 == 16
Again taking advantage of logical operators on binary. Investigate how logical operators work on binary a bit more for really clear understanding of what is going on at the bit level (and how to read hex).
>> is right shift operation.
If you have a number 8, which is represented in binary as 00001000, shifting bits to the right by 3 positions will give you 00000001, which is decimal 1. This is equivalent to dividing by 2 three times.
Division and multiplication by the same number means that you set some bits at the right to zero. The same can be done if you apply a mask. Say, 0xF8 is 11111000 bitwise and if you AND it to a number, it will set its last three bits to zero, and other bits will be left as they are. E.g., 10 & 0xF8 would be 00001010 & 11111000, which equals 00001000, or 8 in decimal.
Of course if you use 32-bit variables, you should have a mask fitting this size, so it will have all the bits set to 1, except for the three bits at the right, giving you your number - 0xFFffFFf8.
>> shifts the number to the right. Consider a binary number 0001000 which represents 8 in the decimal notation. Shifting it 3 bits to the right would give 0000001 which is the number 1 in decimal notation. Thus you see that every 1 bit shift to the right is in fact a division by 2. Note here that the operator truncates the float part of the result.
Therefore i >> n implies i/2^n.
This might be fast depending on the implementation of the compiler. But it generally takes place right in the registers and therefore is very fast as compared to traditional divide and multiply.
The answer to the second part is contained in the first one itself. Since division also truncates all the float part of the result, the division by 8 will in theory shift your number 3 bits to the right, thereby losing all the information about the rightmost 3 bits. Now when you again multiply it by 8 (which in theory means shifting left by 3 bits), you are padding the righmost 3 bits by zero after shifting the result left by 3 bits. Therefore, the complete operation can be considered as one "&" operation with 0xfffffff8 which means that the number has all bits 1 except the rightmost 4 bits which are 1000.

Help to begin in assigning specific bits

So I have a problem for my class that I am having trouble getting started on. I am not asking people to do the problem for me, I just would like any nudge in the right direction. I need to create a function in C that when given any 32 bit integer it returns an integer where every 4th bit is set to a 1 starting at the least sig bit. I understand what it is supposed to look like in the end, but getting started I am lost on. We are not allowed to use any for loops or conditionals, just the standard bitwise and logical operators(! ~ & ^ | + << >>). Once again, I am not asking anyone to do this for me, I just would like some help in getting me thinking on the right track. I have seen some of the other posts on here and on other pages, but none seem to click. I understand that you can bitshift a 1 into a certain place x<<3 but going beyond that I am stuck. Any help would be appreciated.
int get_int_with_every_fourth_bit_set()
{
return 0x88888888;
}
Ok, that was mostly facetious. Here's a list of what the bitwise operators do:
bitwise NOT (~): Toggle a bit, 0 to 1 and 1 to 0
AND (&): Set a bit if the bit in that position is set in both operands
OR (|): Set a bit if the bit in that position is set in either operand
XOR (^): Set a bit if exactly one bit in that position is set between the two operands
Bitwise shift (<< and >>): Move each bit over the specified amount in the given direction. When shifting left, zeros are added to the least significant bit. When shifting right, a zero will be added if the value is either unsigned or positive.
Here are some bitwise tricks that are good to know:
A bitwise shift left by one is the same as multiplying by two. A bitwise shift right by one is the same as dividing by two, and rounding down.
All powers of two have exactly one 1 bit. To see if a number is a power of two, you can do this:
return !(x & (x - 1)) && x
As an example, say x = 16, which is a power of two. Then, x - 1 = 15, so the values to be ANDed are 00010000 and 00001111. Since each bit position has a zero in at least one of the two operands, the result is zero. !0 is true, so check to see if x != 0. Since 16 != 0, the statement returns true. If you try it with a number that is not a power of two and not zero, then the x & (x - 1) check will always be true. So cool!
Another tip: since 0 ^ 0 = 0 and 1 ^ 1 = 0, you can use XOR to see what bits have changes. For example, if you have two bytes and want to see the bits that changed between then, the XOR of the two bytes will give you a 1 in the position of all bits that have changed.
Can you write down (in hex) the 32 bit integer that has every 4th bit set to 1, and all other bits set to 0?
Now, is there an operation you can apply to your input and this magic number, which sets every 4th bit of the input to 1, but leaves the other bits alone?
Check out bitmasking.
...Therefore, to make sure a bit is on, OR can be used with a 1. To leave a bit unchanged, OR is used with a 0.
So the mask for your case (leaving other bits unchanged) would be:
Binary: 10001000100010001000100010001000
Hex: 88888888

Resources