On bit fields usage

B

bitshadow

Hi all,
I'm implementing RFC3550 that requires me to create a header of n
number of bits. I've used a bit field to accomplish this. however i
realise i know little about bit fields and my C primer Plus doesn't go
into too much detail..

assuming i have the following structure:

typedef struct{
unsigned int v: 2;/*rtp version*/
unsigned int p: 1; /*rtp padding*/
unsigned int x: 1;/*extension bit*/
unsigned int cc: 4;/*csrc count*/
unsigned int m: 1;/*marker bit*/
unsigned int pt: 7;/*payload type*/
unsigned int sn: 16;/*sequence number*/
unsigned int ts: 32;/*time stamp*/
unsigned int ssrc: 32;/*synchronization source*/
unsigned int csrc: 32;/*contributing sources max 15*/
char *encoded_audio;
}rtp_hdr;

1)I understand that the bit field is just stored as an unsigned
integer and the total value of the bit field can't exceed the sizeof
unsigned int (32 bits) or 4 bytes is this correct?

2)assuming i have the above structure does that mean then that the
char variable - holding 40 bytes - would run into the first bit int v?


3)if i don't decalare a type and simply do:

typedef struct{
unsigned v: 2;/*rtp version*/
unsigned p: 1; /*rtp padding*/
unsigned x: 1;/*extension bit*/
unsigned cc: 4;/*csrc count*/
unsigned m: 1;/*marker b*
.......}

will the compiler automatically declare them as unsigned int?

4)in order to make sure the amount of bits i need fits into the
header struct does that mean i have to implicity declare short
integers to make them fit.

5)will my compiler store the bits in the way they are layed out or is
it compiler dependant.

thank you, i know its alot of questions (it's not homework) i just
want to make sure i understand how these work
so i can build this.

thank you very much,
Greg
 
K

Keith Thompson

bitshadow said:
I'm implementing RFC3550 that requires me to create a header of n
number of bits. I've used a bit field to accomplish this. however i
realise i know little about bit fields and my C primer Plus doesn't go
into too much detail..

assuming i have the following structure:

typedef struct{
unsigned int v: 2;/*rtp version*/
unsigned int p: 1; /*rtp padding*/
unsigned int x: 1;/*extension bit*/
unsigned int cc: 4;/*csrc count*/
unsigned int m: 1;/*marker bit*/
unsigned int pt: 7;/*payload type*/
unsigned int sn: 16;/*sequence number*/
unsigned int ts: 32;/*time stamp*/
unsigned int ssrc: 32;/*synchronization source*/
unsigned int csrc: 32;/*contributing sources max 15*/
char *encoded_audio;
}rtp_hdr;

1)I understand that the bit field is just stored as an unsigned
integer and the total value of the bit field can't exceed the sizeof
unsigned int (32 bits) or 4 bytes is this correct?

The value of an unsigned int bitfield of width N cannot exceed 2**N-1.
The value of N cannot exceed the width of type unsigned int, which may
or may not be 32 bits; it can be as small as 16 bits, or it can be
arbitrarily wide.
2)assuming i have the above structure does that mean then that the
char variable - holding 40 bytes - would run into the first bit int v?

You don't have a char variable holding 40 bytes. You have a char*
member which may point to the first element of an array, which may
hold 40 bytes. But the encoded_audio pointer isn't going to point
to anything until you assign a value to it.

But I don't think that's what you want.

For one thing, the standard leaves a lot of leeway in how bit fields
are allocated. For details, see the C standard; the latest post-C99
draft is available at
<http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf>. You
can't be sure that your bit fields will be laid out as required by the
RFC.

You also have to worry about byte ordering. The RFC probably requires
a specific representation for each field (probably "network byte
order"); your platform may or may not use that same representation.

For portability, you may have better luck using explicit bitwise
shifts and masks to access the individual fields, rather than
declaring bit fields and hoping that the compiler will generate those
same shifts and masks for you. But if you find that bit fields work,
the convenience just might be worth the potential loss of portability.

Taking a very quick look at RFC 3550, you've defined a structure
that's intended to match the "RTP header", which will be followed
directly in memory by other information. Rather than having the extra
information in your structure, you have a pointer.

This might be a job for the "struct hack" (see question 2.6 in the
comp.lang.c FAQ, <http://c-faq.com/>), or for a "flexible array
member" if your compiler supports this C99 feature.

But it's probably better for your structure to hold just what's
defined for the RTP header. You can then declare another structure
type for each kind of packet, each of which will have a header
structure as its first member.
3)if i don't declare a type and simply do:

typedef struct{
unsigned v: 2;/*rtp version*/
unsigned p: 1; /*rtp padding*/
unsigned x: 1;/*extension bit*/
unsigned cc: 4;/*csrc count*/
unsigned m: 1;/*marker b*
......}

will the compiler automatically declare them as unsigned int?

Yes, the names 'unsigned int' and 'unsigned' are simply different
names for the same type. If you've grabbed a copy of n1124.pdf, see
section 6.7.2, "Type specifiers".
4)in order to make sure the amount of bits i need fits into the
header struct does that mean i have to implicity declare short
integers to make them fit.

No. The only portably supported types for bit fields are int, signed
int, unsigned int, and (C99 only) _Bool. (In most contexts, 'int' and
'signed int' are identical; for bit fields, 'int' may be either signed
or unsigned, at the whim of the compiler. Because of this, don't use
plain int for bit fields.)
5)will my compiler store the bits in the way they are layed out or is
it compiler dependant.

It's compiler dependent.

I'd be surprised if nobody else had already written a C implementation
of RFC 3550. A little bit of Googling could save you a lot of time
and effort (since you say this isn't homework).
 
B

bitshadow

I'd be surprised if nobody else had already written a C implementation
of RFC 3550. A little bit of Googling could save you a lot of time
and effort (since you say this isn't homework).

--
Keith Thompson (The_Other_Keith) (e-mail address removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

Hi keith,
thanks for replying, i'll have a look over what you said and test it
out.
*lol* it honestly isn't homework and there actually are quite a few
libraries out there, however i want to learn about bit fields
and how to manipulate bits and i also want to write RFC3550 directly
into my voip code to make it a little more tight.
 
K

Keith Thompson

bitshadow said:
thanks for replying, i'll have a look over what you said and test it
out.
*lol* it honestly isn't homework and there actually are quite a few
libraries out there, however i want to learn about bit fields
and how to manipulate bits and i also want to write RFC3550 directly
into my voip code to make it a little more tight.

Please don't quote signatures (the portion of the article following
the "-- " marker" unless you're actually commenting on them. The
identify who you're quoting.

You'll find that bit fields and "how to manipulate bits" are two
different things, at least if you want your code to be portable.
 
B

bitshadow

You don't have a char variable holding 40 bytes. You have a char*
member which may point to the first element of an array, which may
hold 40 bytes. But the encoded_audio pointer isn't going to point
to anything until you assign a value to it.

But I don't think that's what you want.

Why don't you think thats what i want? you said it'd be better if i declared another struct to hold the data being sent is there
any problems with doing this:

typedef struct{
rtp_hdr Header;/*modularize for ease of use and no truncating to
unsigned int?*/
char *audio;/*does it matter if i malloc the data or hard code it?*/
}Payload;

before the data is sent i malloc a buffer and fill it with data.
however doing this is it sill being 'corrupted'
somehow? do i have to declare the (char *) in a separate struct so its
not counted as part of the bit field? or is that declaration
okay as long as i malloc it before sending.

as for the way the bits are layed out by the compiler i will be
checking with my compiler doc for that and the link you gave me as
well. intriguing.
 
K

Keith Thompson

bitshadow said:
Why don't you think thats what i want? you said it'd be better if i
declared another struct to hold the data being sent is there any
problems with doing this:

typedef struct{
rtp_hdr Header;/*modularize for ease of use and no truncating to
unsigned int?*/
char *audio;/*does it matter if i malloc the data or hard code it?*/
}Payload;

You're trying to match the data layout defined by RFC whatever-it-was.
I'm 99% certain that the RFC doesn't specify a pointer (i.e., an
internal memory address) in any of its packet definitions.

Pointers are for use in your program to refer to data in memory. If
you're trying to write a pointer to a file, or to a network, or
something similar, you're doing something wrong.

One possible source of confusion is that arrays and pointers can
*appear* to be similar, or even the same thing. They are not. Arrays
are not pointers; pointers are not arrays. For more information on
this, see section 6 of the comp.lang.c FAQ, <http://www.c-faq.com>.
(I typed the URL and section number from memory, since I don't have a
browser running.)
 
B

Ben Bacarisse

bitshadow said:
On Aug 27, 4:21 pm, Keith Thompson <[email protected]> wrote:
any problems with doing this:

typedef struct{
rtp_hdr Header;/*modularize for ease of use and no truncating to
unsigned int?*/
char *audio;/*does it matter if i malloc the data or hard code it?*/
}Payload;

before the data is sent i malloc a buffer and fill it with data.
however doing this is it sill being 'corrupted'
somehow? do i have to declare the (char *) in a separate struct so its
not counted as part of the bit field? or is that declaration
okay as long as i malloc it before sending.

The corruption will, most likely, be coming from something else. The
structures are fine.

What Keith Thompson was most likely referring to when he said "but I
don't think that's what you want" is that in most network code, one
puts the header and payload in one contiguous block of memory because
this (except on *very* interesting hardware) simplifies the interface
to lower-level send and receive functions.
 
B

bitshadow

What Keith Thompson was most likely referring to when he said "but I
don't think that's what you want" is that in most network code, one
puts the header and payload in one contiguous block of memory because
this (except on *very* interesting hardware) simplifies the interface
to lower-level send and receive functions.
Thanks for your reply ben and clarifying that up for me. the previous
code only sends 20bytes even aftter i've malloced and added the
payload and i was wondering where i could have possibly gone wrong. it
tells me the bit field is 20 bytes, the (char *) is four and then the
bytes sent is 20. that means somehow it seems not to be mallocing the
required amount or perhaps not adding the audio i need.

Could it be then its better to hard code the size of the payload since
that will save it one contiguous block of memory: ex:
typedef struct{
rtp_hdr Header;
char audio[MAX_LEN];
}Payload;

is that what you mean by putting the header and payload in one
contiguous block of memory, since if i malloc it i can't gurantee
where it will be.

Thank you very much,
Greg
 
B

Ben Bacarisse

bitshadow said:
Thanks for your reply ben and clarifying that up for me. the previous
code only sends 20bytes even aftter i've malloced and added the
payload and i was wondering where i could have possibly gone wrong. it
tells me the bit field is 20 bytes, the (char *) is four and then the
bytes sent is 20. that means somehow it seems not to be mallocing the
required amount or perhaps not adding the audio i need.

All this is rather unclear. I suspect there may be something wrong
with the code that does the allocation. Showing only struct
declarations does not give enough information.

If the error is in standard stuff like allocation and freeing,
bitfield setting and so on then it is topical here. Best would be a
short compilable example that shows something going wrong.

If the error is in the send/receive protocol stuff, you should post in
a group that discuss your platform/
Could it be then its better to hard code the size of the payload since
that will save it one contiguous block of memory: ex:
typedef struct{
rtp_hdr Header;
char audio[MAX_LEN];
}Payload;

That is often done. Whether it is "better" depends on too many things
to be answerable!
is that what you mean by putting the header and payload in one
contiguous block of memory, since if i malloc it i can't gurantee
where it will be.

Yes. The second part of that, suggests that you might be having
trouble making sure that you are send the data you want to send.
There is not problem having the data in a separate buffer, but you
would then, usually, be sending in two parts -- the header (minus the
'char *' field which is meaningless when sent) and the data pointer to by the
'char *' field.
 
B

bitshadow

Thanks alot ben, for simplicities(sp?) sake i just declared a buffer
size for the payload so i don't have to worry too much about memory
managment. I'll attack the bit format in my compiler forum and verify
to make sure there is nothing wrong on the network side of things as
well.
thanks to you both.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top