0

I am trying to write a C program wherein I will declare two variable of type status bitfield, status a and status mask.And in status a I can only set the bitfields which are already set in mask.

#include<stdio.h>

typedef struct
{
    unsigned int w : 1 ;
    unsigned int x : 1 ;
    unsigned int y : 1 ;
    unsigned int z : 1 ;
}status ;

void bitset(status* a,status* b,int position)
{
    /*Check for the position and set that bit only if it is set in mask.
     In this case, I can set only a.x and a.z.

}
int main()
{
    status a ;
    status mask ;
    int position ;

    mask.w = 0
    mask.x = 1 ;
    mask.y = 0;
    mask.z = 1;

    position = 1 ;

    bitset(&a,&b,position); 
}

For this I tried using & operator.But it is showing error.

Q1: By using pointers to the a and mask how can I complete the function bitset.

Q2: Is there a way so that I can set all the bitfields at once,something like a = 0x10 so that only y bit is set.

Q3: Is there a way so that I can reset all the bits at once,like a={0}.Is this the correct way to do it? Please help.

2 Answers2

1

A2: not in a portable way; you can put it into a union with an integer member and shuffle the bitfields so that it works for your ABI. But as said, this is not portable

A3: memset(&a, 0, sizeof a) should do it

BUT: bitfields are ugly and probably the wrong choice for you use case. I would use unsigned integers for it.

ensc
  • 6,704
  • 14
  • 22
0

A1: If you want to set a bit you should use OR operator, not AND. The access to bits via pointer is similar to the one via variable. The only difference is in "->" instead of ".". I.e. a->w and not a.w;

A2: Yes, there is. For example, declare an integer pointer to the same memory location and use it to access the memory as integer variable. See example code below. Downside is that you get access to all the bits your struct is occupying.

A3: Same as A2. If you can set, you can also reset.

#include <stdio.h>

typedef struct {
  int a:1;
  int b:1;
  int c:1;
  int d:1;
} bitField;

int main() {
  bitField A;
  bitField B;

  int *allA;
  allA = (int *)&A;     //Access bitField as Integer

  *allA = 0x02;         //Set bit 2 of A
  printf("A=0x%x\n", A);

  *allA = 0x53;         //Set bits 1 and 2 of A, but also set a few of "out of range" bits
  printf("A=0x%x\n", A);

  *allA = 0x01;         //Set bit 1, reset all other bits
  printf("A=0x%x\n", A);

  B.c = 1;              //Set Bit 3 of B

  A.c |= B.c;           //A=0b0001, B=0b0100 -> A|B=0b0101 (dec 5)
  printf("A=0x%x\n", A);

  int *allB;
  allB = (int *)&B;

  *allA = 0;
  *allB = 3;
  *allA |= *allB;       //Set bits 1 and 2 of A by OR-ing with B;
  printf("A=0x%x\n", A);
}
Sokre
  • 114
  • 6
  • The use of bitfield operations and int-wide bitwise operations on the same variable is not portable. E.g., on a bigendian machine it is likely that B.c is not bit 3 but bit sizeof(int) * 8 - 3. – Doug Currie May 17 '17 at 22:53
  • Hi Sokre, I cant use OR operator for setting the bit because the condition is I can set only the bits that are already set in the Mask bitfield in your case say bitfield b.So If B = 0b0100 and I want to set the first bit of bitfield a i.e 0b0001 , I should not be able to do that .As per the condition I can set and reset only the 3rd bit of a .(B = 0b0100).Thats why I wanted to use AND operator – Gopal Krishna May 18 '17 at 04:20
  • Hi, then you shoud AND the MASK with B and OR the result with A. AND-ing will leave only bits in both B and mask standing and OR-ing will will set the resulting bits in A. Of course, assuming A was reset before all of that. – Sokre May 18 '17 at 09:51
  • @Doug Currie - you might be right, but I have my doubts about that. For the sake of this dicussion, I don't see why would it matter how a "bitwise split" integer is stored in memory, when OR-ing/AND-ing is going to be performed on registers. The defined struct has integer as underlying type. When integer is loaded from memory into a register, it is going to be "sorted out right". Or? – Sokre May 18 '17 at 11:55
  • @Skore, no, the processor will not flip bits end to end when reading/writing to memory. It's unfortunate that C does not specify the layout of bit fields within ints; you cannot depend on it. See https://www.securecoding.cert.org/confluence/display/c/EXP11-C.+Do+not+make+assumptions+regarding+the+layout+of+structures+with+bit-fields and http://stackoverflow.com/questions/6043483/why-bit-endianness-is-an-issue-in-bitfields – Doug Currie May 18 '17 at 15:10
  • @Doug Currie, yes, the correct explanation is that the order of bits in a bitfield is unspecified and therefore compiler implementation dependent and not portable. There is however no relation to endianness. Whether portability is really an issue here can only be answered by Gopal. With a bit of tweaking he can do what he intends to. – Sokre May 18 '17 at 15:59