Adil.Kolenko
Adil.Kolenko

Reputation: 89

What does a combination "&" with " -" mean?

Does anyone know what does &- in C programming?

limit= address+ (n &- sizeof(uint));

Upvotes: 3

Views: 215

Answers (2)

Lundin
Lundin

Reputation: 213306

&- is the binary bitwise AND operator written together with - which is the unary minus operator. Operator precedence (binary & having lowest precedence here) gives us the operands of & as n and -sizeof(uint).

The purpose is to create a bit mask in a very obscure way, relying on unsigned integer arithmetic. Assuming uint is 4 bytes (don't use homebrewed types either btw, use stdint.h), then the code is equivalent to this

n & -(size_t)4

size_t being the type returned by sizeof, which is guaranted to be a large, unsigned integer type. Applying unary minus on unsigned types is of course nonsense too. Though even if it is obscure, applying minus on unsigned arithmetic results in well-defined wrap-around1), so in case of the value 4, we get 0xFFFFFFFFFFFFFFFC on a typical PC where size_t is 64 bits.

n & 0xFFFFFFFFFFFFFFFC will mask out everything but the 2 least significant bits.

What the relation between these 2 bits and the size of the type used is, I don't know. I guess that the purpose is to store something equivalent to the type's size in bytes in that area. Something with 4 values will fit in the two least significant bits: binary 0, 1, 10, 11. (The purpose could maybe be masking out misaligned addresses or some such?)

Assuming I guessed correct, we can write the same code without any obfuscation practices as far more readable code:

~(sizeof(uint32_t)-1)

Which gives us 4-1 = 0x3, ~0x3 = 0xFFFF...FC. Or in case of 8 byte types, 0xFFFF...F8. And so on.

So I'd rewrite the code as

#include <stdint.h>

uint32_t mask = ~(sizeof(uint32_t)-1);
limit = address + (n & mask);

1) C17 6.3.1.3

Otherwise, if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type60)

Where the foot note 60) says:

The rules describe arithmetic on the mathematical value, not the value of a given type of expression.

In this case repeatedly subtracting SIZE_MAX+1 from 4 until the value is in range of what can fit inside a size_t variable.

Upvotes: 3

Daniel Kleinstein
Daniel Kleinstein

Reputation: 5502

This isn't really one operator, but two:

(n) & (-sizeof(uint))

i.e. this is performing a bitwise and operation between n and -sizeof(uint).


What does this mean?

Let's assume -sizeof(uint) is -4 - then by two's complement representation, -sizeof(uint) is 0xFFFFFFFC or

1111 1111 1111 1111 1111 1111 1111 1100

We can see that this bitwise and operation will zero-out the last two bits of n. This effectively aligns n to the lowest multiple of sizeof(uint).

Upvotes: 11

Related Questions