the foll code when run on gcc compiler gave 12 as output
struct aa{char a:3;int b:30;char c:3;}; printf("%d",sizeof(struct aa));

but when i replace size of c to 2 then it gives 8 why is that so?? sizeof int is 4 and char is 1..

struct aa {
    char a:3;  // the least significant 3 bits of the char
    int b:30;  // bits 0 to 29 of the integer
    char c:3;

With regular 4 byte alignment, you'll have a, b and c each using 4 bytes = 12 bytes.

but when i replace size of c to 2 then it gives 8 why is that so?

I'm unable to reproduce this, with char c:2 the same alignment applies and should produce a size of 12 bytes.

In gcc it gives 8 as output....and also if you interchange positions of char a and int b it gives 8...

Here's you're example with some padding to show what happens when b and c are interchanged.

struct aa {
    char a:3;      // bits 0..2 of char
    char c:2;      // bits 3..4 of same char
    char unused:3  // most significant 3 bits of the same char
    char pad[3];   // pad to 4 byte boundary
    int b:30;      // bits 0..29 of int

This would give a size of 8 bytes.
Unfortunately, I don't have a gcc compiler with me at the moment to explain why the following would also produce a size of 8.

struct aa {
    char a:3;
    int b:30;
    char c:2;