Size of my Struct? PLZ PLZ reply

B

brian

ANaiveProgrammer said:
Last but not the least , i need to send the ethernet_frame struct over
a socket , is the following a legitimate way to do that
write(sockfd,(char *)&ef,10);//'ef' is the instance of ethernet_frame
struct
Please tell me how to send a struct over the socket, is above way
correct OR there is another around?
Any help, at earliest, would highly be appreciated. I know its a
lenghty post and may take a bit of your time. However, i will be
highly compelled for this esteemed favour.
Cheers
Waqas

This has already been done in libnet. I would suggest checking out
the source code for that library.

Also, there is more than one type of ethernet header you can send.
Check out the RFCs. You might also want to read TCP Illustrated
vol I.

Finally, write() is a unix system call, which is out of scope for
this newsgroup even though K&R mention it in their book. And you
want to test the buffering to make sure everything you want to send
actually got sent. Don't forget to use good error coding.

comp.unix.programmer might be able to help you out more.

Brian

ps And the size of structs is covered in the FAQ.
 
A

ANaiveProgrammer

Hi all

I have made the following two structs and size is not according to
what is supposed to be, so please ponder over following and identify
if im wrong...
please also mention what would be the size of "ethernet_frame" struct
and why ?

typedef struct {
//This struct defines Arp--Request.
uint8_t haddr_type
uint8_t proto_type[4];
uint8_t hard_len;
uint8_t proto_len
uint16_t operation;
uint8_t sender_hard[6];
uint8_t sender_proto[4];
uint8_t target_ip[4];

}arp_request;

typedef struct{
//Ethernet Frame
uint8_t destip[4];
uint8_t sourceip[4];
uint8_t frametype[3];
arp_request *req;
} ethernet_frame;

int main(){
arp_request request;
ethernet_frame ef;

printf("Size of ARP---%d\n",sizeof(request));
printf("Size of Ethernet---%d\n",sizeof(ef));
}
--------

im compiling this code under Red Hat linux(PSyche)...
My second question is that how will i initialize a uint8_t array, for
example

As i have defined a uint8_t frametype[3]in ethernet_frame struct...i
have defined this unsigned integer array in another function as
follows

uint8_t frame[3]={0x8,0x0,0x6};
for( k=0; k<3;k++)
ef->frametype[k] = frame[k];
//where 'ef' is a pointer to ethernet_frame struct
Well im very much sure that there would be some better way around than
above in terms of code optimization. please answer this question as
well???

Last but not the least , i need to send the ethernet_frame struct over
a socket , is the following a legitimate way to do that
write(sockfd,(char *)&ef,10);//'ef' is the instance of ethernet_frame
struct
Please tell me how to send a struct over the socket, is above way
correct OR there is another around?
Any help, at earliest, would highly be appreciated. I know its a
lenghty post and may take a bit of your time. However, i will be
highly compelled for this esteemed favour.
Cheers
Waqas
 
E

Eric Sosman

ANaiveProgrammer said:
Hi all

I have made the following two structs and size is not according to
what is supposed to be, so please ponder over following and identify
if im wrong...

This is Question 2.13 in the comp.lang.c Frequently
Asked Questions (FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html
please also mention what would be the size of "ethernet_frame" struct
and why ?

The correct answer is `sizeof(ethernet_frame)' and the
"why" is "because."
 
J

Jens.Toerring

ANaiveProgrammer said:
I have made the following two structs and size is not according to
what is supposed to be, so please ponder over following and identify
if im wrong...
please also mention what would be the size of "ethernet_frame" struct
and why ?
typedef struct {
//This struct defines Arp--Request.
uint8_t haddr_type
uint8_t proto_type[4];
uint8_t hard_len;
uint8_t proto_len
uint16_t operation;
uint8_t sender_hard[6];
uint8_t sender_proto[4];
uint8_t target_ip[4];

}arp_request;
typedef struct{
//Ethernet Frame
uint8_t destip[4];
uint8_t sourceip[4];
uint8_t frametype[3];
arp_request *req;
} ethernet_frame;
int main(){
arp_request request;
ethernet_frame ef;
printf("Size of ARP---%d\n",sizeof(request));
printf("Size of Ethernet---%d\n",sizeof(ef));
}
--------
im compiling this code under Red Hat linux(PSyche)...

The size of both structures is determined by the compiler and may
depend on the hardware the program is compiled for. The compiler
is allowed to insert as many padding bytes into the structure as
it deems necessary, see the C-FAQ, section 2.12/13. For that
reason it is _not_ a good idea to try to assemble binary data
in a certain format by using structures. You have to use a "flat"
memory region and populate it by copying the elements into that
region using memcpy(). Only if you don't mind making your program
dependend on the compiler you use then you can use some compiler-
specific extensions to make sure the compiler does not insert
padding bytes (but even in that case you may still have to popu-
late the elements of the structure using memcpy() since on many
machines you may get a bus error when trying to access the
structure elements because the hardware allows only accesses to
e.g. even addresses).
My second question is that how will i initialize a uint8_t array, for
example
As i have defined a uint8_t frametype[3]in ethernet_frame struct...i
have defined this unsigned integer array in another function as
follows
uint8_t frame[3]={0x8,0x0,0x6};
for( k=0; k<3;k++)
ef->frametype[k] = frame[k];
//where 'ef' is a pointer to ethernet_frame struct
Well im very much sure that there would be some better way around than
above in terms of code optimization. please answer this question as
well???

Well, you can use memcpy() (or memmove() in case the data you want to
copy could overlap). If that is faster in your case can only be deter-
mined experimentally. The C language does not make any promises about
the execution speed of a program.
Last but not the least , i need to send the ethernet_frame struct over
a socket , is the following a legitimate way to do that
write(sockfd,(char *)&ef,10);//'ef' is the instance of ethernet_frame
struct
Please tell me how to send a struct over the socket, is above way
correct OR there is another around?

Well, now you rather left the field of what's topical in this group.
The C language has no built-in support for network operations and
also the write() function is not a standard C function but system
dependend. Since you seem to be using Linux the newsgroups
comp.os.linux.development.apps or comp.unix.programmer would seem
to be good places to ask instead.

But typically sending structures in binary form is a bad idea since
the machines on both ends may have quite different ideas about the
lay-out of the structure (e.g. because different amounts of padding
bytes are used) and since the way numbers are represented may differ
a lot between machines with different architectures (look up e.g. the
difference between "big-endian" and "little-endian" machines). It
will probably work when both machines have the same architecture
and the programs on both ends have been compiled with the same
compiler (using the same version of that specific compiler and the
same compiler flags), but otherwise it can fail miserably. It's
the same problem as with writing structures into a file in binary
format and then trying to read them back on a different machine.
One solution would be to convert the data into some common repre-
sentation (e.g. ASCII), send them over to the other side in that
form and then assemble them back into a structure on the other
machine.
Regards, Jens
 
G

Gordon Burditt

I have made the following two structs and size is not according to
what is supposed to be,

If you think the size of a particular struct is supposed to be some
particular integer, regardless of implementation, STOP THINKING
THAT. The size of a particular struct is obtained by using the
sizeof operator. The implementation is always allowed to add padding
to the end of or in the middle of the struct.


Why would something likely to be transmitted over a network
(your ethernet_frame struct) contain a *POINTER*?

Last but not the least , i need to send the ethernet_frame struct over
a socket , is the following a legitimate way to do that
write(sockfd,(char *)&ef,10);//'ef' is the instance of ethernet_frame
struct

The size of ef is sizeof(ef), not 10 or any other explicit integer.
The layout of structures varies from implementation to implementation,
so there is no guarantee that the sending and receiving machine
agree on the size, byte order, alignment, padding, etc. of a raw
binary structure.

Gordon L. Burditt
 
A

ANaiveProgrammer

Many thanks for your reply...
The size of ef is sizeof(ef), not 10 or any other explicit integer.
The layout of structures varies from implementation to implementation,
so there is no guarantee that the sending and receiving machine
agree on the size, byte order, alignment, padding, etc. of a raw
binary structure.

So bottom line is , my structurs will work?????????am i right.....


what is padding in structures, why do compilers do that ? i mean im
stupmed about this....wht is the advantange of using Byte padding in
structures....
cheers
 
J

Jens.Toerring

ANaiveProgrammer said:
Many thanks for your reply...
So bottom line is , my structurs will work?????????am i right.....

Where did you got that from Gordons reply (and, please, keep proper
attributions)?
what is padding in structures, why do compilers do that ? i mean im
stupmed about this....wht is the advantange of using Byte padding in
structures....

The advantage of padding bytes is that the compiler can produce
code that won't crash with bus errors on some machines. There are
quite a number of machines where accessing e.g. odd addresses is
not allowed. So, when you have e.g. a structure like

struct crash_me {
int a;
char b;
int c;
} x;

and sizeof(int) is at an even and sizeof(char) an odd number, then,
without an additional padding byte, 'c' would be at an odd address
(the compiler makes sure that the structure does not start at an
odd address in such cases). And the result would be that for

x.c = 3;

the computer would have to write a value to an int that is at an odd
address and that would kill the program. In order to avoid that the
compiler automatically inserts at least one "padding byte" between
the members 'b' and 'c' of the structure, so that accessing the member
'c' won't lead to the program getting aborted.

You are also for example not allowed to do things like

int a;

*( ( char * ) a + 1 ) = 1;

because that could result in an "unaligned" access, i.e., in the example
from above, in an access to an odd address.

That's probably the main reason for padding bytes. But even on machines
where accesses to odd addresses are allowed it's often a lot slower
than accessing even addresses (e.g. i386 CPUs).

Regards, Jens
 

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

Members online

Forum statistics

Threads
473,734
Messages
2,569,441
Members
44,832
Latest member
GlennSmall

Latest Threads

Top