9 Replies - 979 Views - Last Post: 05 April 2012 - 08:08 PM Rate Topic: -----

#1 Vermiculus  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 10
  • View blog
  • Posts: 314
  • Joined: 26-February 09

Specific bit access with C unions

Posted 05 April 2012 - 07:54 AM

Hey all, is this sort of thing is possible? It's throwing a syntax error when I use the array, but accessing it through b1, b2, etc. just reveals all HI bits, no matter what I store.

I'm using GCC.

Any help would be greatly appreciated :)

union BYTE {
	unsigned char byte;
	unsigned int b[8]:1;
//	unsigned int b1:1;
//	unsigned int b2:1;
//	unsigned int b3:1;
//	unsigned int b4:1;
//	unsigned int b5:1;
//	unsigned int b6:1;
//	unsigned int b7:1;
};

union BYTE b;
b.byte = 'a';
printf("BYTE: char:%c int:%d bits:%d%d%d%d%d%d%d%d",
	   b.byte,
	   b.byte,
	   b.b[0],
	   b.b[1],
	   b.b[2],
	   b.b[3],
	   b.b[4],
	   b.b[5],
	   b.b[6],
	   b.b[7]);


Is This A Good Question/Topic? 0
  • +

Replies To: Specific bit access with C unions

#2 simeesta  Icon User is offline

  • Deadly Ninja


Reputation: 218
  • View blog
  • Posts: 590
  • Joined: 04-August 09

Re: Specific bit access with C unions

Posted 05 April 2012 - 08:15 AM

You can't do that as you can't have arrays of bit fields. The last 3 paragraphs here give a little bit more information on it.

This post has been edited by simeesta: 05 April 2012 - 08:54 AM

Was This Post Helpful? 0
  • +
  • -

#3 ishkabible  Icon User is offline

  • spelling expret
  • member icon




Reputation: 1622
  • View blog
  • Posts: 5,709
  • Joined: 03-August 09

Re: Specific bit access with C unions

Posted 05 April 2012 - 08:20 AM

"this sort of thing" is possible but not how you're doing it.

anyway, I saw a neat way of doing this. you make a class that accepts an integer a template argument. this class contains an integer(or array of integers) of some size and acts like a bool for the bit of this integer specified in the template argument. now this seems silly until you put these in a union; then it allows you to access the bits statically and use the same integer. again however, this is a C++11 feature because you can't use classes in unions in C++98/03. you can even recursively apply the union using a template to provide an arbitrary number of bits and provide a simple method for accessing them(I'm doing that when I get home :P).

the C++98/03 way to do this would be to use a bitset or something like it, that did this dynamically.

edit:
here's untested idea of how that would work

template<int num_of_bits>
union static_bit_set {
    static_bit<num_of_bits> head;
    static_bit_set<num_of_bits - 1> tail;
};

template<>
union static_bit_set<0> {
    static_bit<0> head;
};

template<int bit_pos, int size>
bool get_bit(const static_bit_set<size>& x) {
    return get_bit<bit_pos - 1>(x.tail);
} 
template<int size>
bool get_bit<0, size>(const static_bit_set<size>& x) {
    return x.head;
} 


This post has been edited by ishkabible: 05 April 2012 - 10:13 AM

Was This Post Helpful? 0
  • +
  • -

#4 jimblumberg  Icon User is offline

  • member icon


Reputation: 3983
  • View blog
  • Posts: 12,261
  • Joined: 25-December 09

Re: Specific bit access with C unions

Posted 05 April 2012 - 08:31 AM

You can't use bitfields in a union, but you can use bit fields in a structure. And as long as your bit field structure members add up to be the same size as an int you should be able to use that structure in your union. For example:

#include <stdio.h>
#include <stdlib.h>

typedef struct bits
{
	unsigned b1:1;
	unsigned b2:1;
	unsigned b3:1;
	unsigned b4:1;
	unsigned b5:1;
	unsigned b6:1;
	unsigned b7:1;
	unsigned b8:1;
}Bits;

union BYTE {
	unsigned char byte;
	unsigned int inByte;
	Bits b;
};

int main(void)
{
   union BYTE b;
   //b.byte = 'a';
   b.inByte = 97;
   printf("BYTE: char:%c int:%d\n",b.byte, b.inByte);
   printf("%u %u %u %u %u %u %u %u", b.b.b8, b.b.b7, b.b.b6, b.b.b5, b.b.b4, b.b.b3, b.b.b2, b.b.b1);

   return(0);
}



Also note that in the above code if you try to use the char to populate your union the int will not print the correct value.
See this link on bit fields.


Jim

This post has been edited by jimblumberg: 05 April 2012 - 08:38 AM

Was This Post Helpful? 0
  • +
  • -

#5 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5749
  • View blog
  • Posts: 12,556
  • Joined: 16-October 07

Re: Specific bit access with C unions

Posted 05 April 2012 - 08:42 AM

It's rather complex approach for what you want. In C you can ask about the individual bits with relative ease. No need for special structures. If you want a nice neat package:
#define BIT(value, bitNum) ((value & (0x80 >> bitNum))?1:0)

char a = 'a';
printf("BYTE: char:%c int:%d bits:%d%d%d%d%d%d%d%d\n",
	a, a, 
	BIT(a,0),
	BIT(a,1),
	BIT(a,2),
	BIT(a,3),
	BIT(a,4),
	BIT(a,5),
	BIT(a,6),
	BIT(a,7));


Was This Post Helpful? 0
  • +
  • -

#6 Vermiculus  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 10
  • View blog
  • Posts: 314
  • Joined: 26-February 09

Re: Specific bit access with C unions

Posted 05 April 2012 - 09:33 AM

I'm sorry that I didn't really clarify, but I need to both read and write individual bits in a byte (ideally an arbitrary-length bitstream). Sorry baavgai, but that BIT macro is just that - a macro, and can't act as an Lval. :/

AND OHMYGOODNESS ishkabible that look so awesome. Unfortunately, C doesn't 'do' templates at all - and I'd really like to stick to ANSI C.

jimblumberg has basically what I need, but is there any way to make it so we can access the bits through array notation? Obviously we can't just throw it in an array, because bitfields don't have their own address to dereference. Is there any way we can use void*?
Was This Post Helpful? 0
  • +
  • -

#7 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5749
  • View blog
  • Posts: 12,556
  • Joined: 16-October 07

Re: Specific bit access with C unions

Posted 05 April 2012 - 09:53 AM

View PostVermiculus, on 05 April 2012 - 11:33 AM, said:

Sorry baavgai, but that BIT macro is just that - a macro, and can't act as an Lval.


The byte is the lval, so I don't really see your point. But, hey, glad you got an answer that worked for you.

The :x notation, afaik, is not consistent across all systems. Bit shifts are. Keep in mind that the smallest element you can address in C is a char. ( Though, in practice, it's usually larger. )

Don't get stuck on array notation or any kind of syntax. Concentrate on whatever problem you're trying to solve.
Was This Post Helpful? 0
  • +
  • -

#8 Vermiculus  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 10
  • View blog
  • Posts: 314
  • Joined: 26-February 09

Re: Specific bit access with C unions

Posted 05 April 2012 - 10:06 AM

======================================================

Perhaps it would be best if I describe what exactly I'm trying to do.

I have a function whose signature is char* modify(char* original, char* modifier, int mod_size), where original is a variable-length string (guaranteed to be divisible into bytes) and modifier is a 'string' of 'bytes', where I'm actually trying an attempt at a bitstring. The trick is that I know for a fact that modifier will never be divisible into bits, and will usually be much smaller than original. In the case that it's smaller, I need something like this to happen:

0100100101011101 (original, 2 bytes long)
0110110110110110 (modifier, 3 bits long, repeated and truncated to the length of the bitstream)
(some logical operation) (modified, 2 bytes long)

Does anyone know how I can effect this?

EDIT:

View Postbaavgai, on 05 April 2012 - 12:53 PM, said:

Don't get stuck on array notation or any kind of syntax. Concentrate on whatever problem you're trying to solve.

It seems that I may have a shred of wisdom in me yet. ;)

EDIT:
mod_size is an integer length of the modifier-bitstream.

This post has been edited by Vermiculus: 05 April 2012 - 10:07 AM

Was This Post Helpful? 0
  • +
  • -

#9 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon

Reputation: 5749
  • View blog
  • Posts: 12,556
  • Joined: 16-October 07

Re: Specific bit access with C unions

Posted 05 April 2012 - 12:13 PM

Not 100% sure I'm following that. It looks like your modify is missing a parameter, though.

Maybe this will get you started:
#include <stdio.h>

void showBits(void *data, int bits);
void showBytes(void *data, int bytes);
void *modify(void *src, int srcSizeInBits, void *modifier, int modSizeInBits);

int main(int argc, const char* argv[]) {
	char n[2] = { 0b01001001, 0b01011101 };
	char mod = 0b01100000;
	printf("n = "); showBytes(n, 2); printf("\n");
	printf("mod = "); showBits(&mod, 3); printf("\n");
}

void showBits(void *data, int bits) {
	int mask = 0x80;
	const char *p = data;
	while(bits-- > 0) {
		printf("%d", ((mask & *p)!=0));
		mask >>= 1;
		if (!mask) {
			p++;
			mask = 0x80;
		}
	}
}

void showBytes(void *data, int bytes) { showBits(data, bytes * 8); }



A modify as described could be a variation of showBits for walking over the data. Depending on the operation, a simple mask operation could be a challenge, but should be doable. Note that not all OSes have 8 bit characters, but most do...
Was This Post Helpful? 0
  • +
  • -

#10 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 1072
  • View blog
  • Posts: 4,531
  • Joined: 09-June 09

Re: Specific bit access with C unions

Posted 05 April 2012 - 08:08 PM

Quote

I'm sorry that I didn't really clarify, but I need to both read and write individual bits in a byte


You can use bit level logic to set and zero bits.

example
#include <stdio.h>

//set bit n in c to 1
void set_bit(char *c, int n) {
	*c = *c | 1 << n;
}

//set bit n in c to 0
void zero_bit(char *c, int n) {
	*c = *c & ~(1 << n);
}

//display bits
void show_bits(char c) {
	for(int i=7; i>=0; i--) {
		printf("%d", (c & (1 << i)) >> i);
	}
}
int main() {
	char a = 1;     //a = 0
	set_bit(&a, 0); //a = 1
	set_bit(&a, 1); //a = 3
	zero_bit(&a, 1);//a = 1
	set_bit(&a, 3); //a = 9
	show_bits(a);   //a = 00001001

	getchar();
	return 0;
}



Note that I used decimal values rather than characters. Feel free to ask if you have any questions about the bit logic

This post has been edited by jjl: 05 April 2012 - 08:27 PM

Was This Post Helpful? 1
  • +
  • -

Page 1 of 1