-2

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 ?

Laodis
  • 17
  • 5
  • 3
    Does this answer your question? [How does the bitwise complement operator (~ tilde) work?](https://stackoverflow.com/questions/791328/how-does-the-bitwise-complement-operator-tilde-work) – moo Feb 11 '20 at 14:22
  • 1
    As for what the code itself does, it basically rounds it up to the nearest 4K boundary. (4096 is 2¹², which means it is a 1 followed by 12 zeroes in binary, so 4096-1 is a number with 12 ones in binary. Its complement `~` is the opposite, so ANDing `&` with it makes the 12 lowest bits of the result zero. The addition beforehand makes it round up and not down.) – Arkku Feb 11 '20 at 14:36

3 Answers3

4

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.

Caleb
  • 124,013
  • 19
  • 183
  • 272
2

~ 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.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Just a minor side note: *'After that'* implies that the right operand of the binary operator is calculated before the left one, but actually that's implementation defined... – Aconcagua Feb 11 '20 at 15:05
1

& 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
Lucas Gras
  • 961
  • 1
  • 7
  • 22