Suppose I have
struct A
{
signed char a:1;
unsigned char b:1;
};
If I have
A two, three;
two.a = 2; two.b = 2;
thre
The rules in this case are no different than in case of full-width arithmetic. Bit-fields behave the same way as the corresponding full-size types, except that their width is limited by the value you specified in the bit-field declaration (6.7.2.1/9 in C99).
Assigning an overflowing value to a signed bit-field leads to implementation-defined behavior, which means that behavior you observe with bit-field a is generally not portable.
Assigning an overflowing value to an unsigned bit-field uses the rules of modulo arithmetic, meaning that the value is taken modulo 2^N, where N is the width of the bit-field. This means, for example, that assigning even numbers to your bit-field b will always produce value 0, while assigning odd numbers to such bit-field will always produce 1.