开发者

Bit operations in C

开发者 https://www.devze.com 2022-12-13 11:25 出处:网络
So if I have an integer that is 32 bits. The first 28 bits (from left) are to store the size of a memory chunk, the next two are 0s and the last two are:

So if I have an integer that is 32 bits. The first 28 bits (from left) are to store the size of a memory chunk, the next two are 0s and the last two are:

What I am trying to do is to know how to turn the flag on and off on the isLast operation and the isUsed operation.

(If we consider only the last two integers (again, we start left) then 01 would be not last and is used for example, one more example is 11 is last and is used, 00 is not last and not used.)

I want to be able to turn the flags on and off in an easy way. I know I will need to use bit operations including & and | but I am not sure how.

Please ask me questions if you need more description of the problem.


//turn on isUsed
data |= 1;
//turn off isUsed
data &= ~1;
//turn on notLast
data &= ~2;
//turn off notLast
data |= 2;


This is very simple:

/* Turn on bit 0 */
code = code | 1;

/* Turn off bit 0 */
code = code & ~1;

/* Turn on bit 1 */
code = code | 2;

/* Turn off bit 1 */
code = code & ~2;

See Bitwise operators in C, or Google for the appropriate terms. You can find this in any book or tutorial about C.


In general, counting the least significant bit as 0, to set bit N, you need to OR the original value with 1 << N.

Eg to set bit 1:

val |= (1 << 1);

To clear bit N, you need to AND the original value with the bit-wise inverse of 1 << N.

Eg to clear bit 1:

val &= ~(1 << 1);


This is begging for an interface, either with functions or macros, something like:

// Use unsigned ints (assuming that's your 32-bit type).

#define setLast(x)   (x) |=  2
#define clrLast(x)   (x) &= ~2
#define isLast(x)    ((x) &  2)

#define setUsed(x)   (x) |=  1
#define clrused(x)   (x) &= ~1
#define isUsed(x)    ((x) &  1)

You can also provide macros to extract the size portion and create the whole integer:

#define getSize(x) ((x) >> 4)
#define create (sz,last,used) \
    (((sz) & 0x0fffffff) << 4) | \
    (((last) & 1) << 1) | \
    (((used) & 1))

You'll find your code becomes a lot more readable if you provide the "functions" to do the work and give them sensible names like the above. Otherwise your code is peppered with bit manipulation instructions that are harder to understand.

Just keep in mind the normal rules for macros, things like not passing in things like x++ if your macros use it more than once (which isn't actually the case here). If you want to be ultra-safe, you can do them as functions.

Equivalent functions would be:

unsigned int setLast (unsigned int *x) { *x |=  2; return *x; }
unsigned int clrLast (unsigned int *x) { *x &= ~2; return *x; }
unsigned int isLast  (unsigned int  x) { return x & 2; }

unsigned int setUsed (unsigned int *x) { *x |=  1; return *x; }
unsigned int clrUsed (unsigned int *x) { *x &= ~1; return *x; }
unsigned int isUsed  (unsigned int  x) { return x & 1; }

unsigned int getSize (insigned int  x) { return x >> 4; }
unsigned int create  (unsigned int sz, unsigned int last, unsigned int used) {
    unsigned int ret =
        ((sz & 0x0fffffff) << 4) |
        ((last & 1) << 1) |
        ((used & 1));
    return ret;
}


Turn the flag on:

register |= (1<<LAST_BIT);

Turn the flag off:

register &= ~(1<<LAST_BIT);

Another way is to use union bit-fields:

union
{
  uint32_t value;
  struct
  {
    unit32_t body:28;
    unit32_t reserved:2;
    unit32_t last_bit:1;
    unit32_t used_bit:1;
  } fields;
} MyResister;

MyResister.fields.last_bit = 1;
MyResister.fields.used_bit = 0;


I would throw in a BIT(x) macro just to make the source code more clear:

#define BIT(n) (0x1U << (n))

Which would result in:

#define LAST_SET(x) ((x) |= BIT(1))
#define LAST_CLR(x)  ((x) &= ~BIT(1))

Also, as previously noted, always put the parameter in parenthesis.

(OT) Edit: Changed name of macro as I do not like having the verb first. First of all a function like getWhatever is for code where you can group the function in a class. In C, IMHO, you should put the "component" name first such as, timeGet() et c

(OT2) Also if it's a register macrofication like this is nice which would result in better portability:

#define MY_REG_RD() (MY_REG)
#define MY_REG_WR(x) (MY_REG = (x))
#define MY_REG_SET(x) (MY_REG |= (x))
#define MY_REG_CLR(x) (MY_REG &= ~(x))
#define MY_REG_DIS BIT(10)
#define MY_REG_EN BIT(4)

Then you could do:

MY_REG_SET(MY_REG_EN);


bool isBitOn( int mask , int i ){ // returns True if i-Th bit is On
    return mask & ( 1 << i ) ;
}

int BitOn( int mask , int i ){ // Turn On the i-Th bit of the value and then returns it
    return mask | ( 1 << i ) ;
}

int BitOff( int mask , int i ){ // Turn Off the i-Th bit of the value and then returns it
    return mask - ( 1 << i ) ;
}

int BitToggle( int mask , int i ){ // Toggle the i-Th bit of the value and then returns it
    return mask ^ ( 1 << i ) ;
}

void printbit(int n) { // print the Binary representation of a Integer Number
    for(int i = 31 ; i >=0 ; i-- )
        printf("%d", isBitOn(n,i) );
    printf("\n");
}
0

精彩评论

暂无评论...
验证码 换一张
取 消