Bit operations in C

六月ゝ 毕业季﹏ 提交于 2019-12-01 09:26:12

问题


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:

  • to store the if it is the last node and then
  • to store if it is used or not (respectively).

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.


回答1:


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



回答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.




回答3:


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);



回答4:


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;
}



回答5:


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;



回答6:


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);



回答7:


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");
}


来源:https://stackoverflow.com/questions/1873505/bit-operations-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!