Re: Programming question: sizeof struct?
Joop Stakenborg writes: Hi there, The upstream maintainer of one of my packages is having problems with his code. I thought it would be nice to use the debian mailing lists, to see if we can an answer on this. I will forward any solution to him. -- The reason why I have not released LogConv 1.54 for Linux is that I am having problems with packed structures that is causing some file formats to not be handled properly. Even though I specify -fpack_struct the generated code does not appear to actually do this. Structure fields are offset and the return from sizeof() returns a value that is not valid. The return value from sizeof _is_ valid. It returns the amount of memory the object occupies in memory. Maybe you don't like it, but that is another issue. For instance, if the structure were: struct foo { char text[3]; int num; }; sizeof would return 6 and not 5. Um, I get 8 instead of 7 (an int is usually 4 bytes in linux): oef.c #include stdio.h struct A { char a[3]; int b; }; int main(void) { printf(%u\n, (unsigned) sizeof(struct A)); return 0; } If I compile and run like this: $ gcc -O2 -o oef oef.c $ ./oef 8 ... I do get padding, and if I compile and run like this: $ gcc -fpack-struct -O2 -o oef oef.c $ ./oef 7 ... I don't get padding. This is using gcc 2.7.2.3. I can imagine that there exist optimization options that affect this though, especially the -malign-... type. Maybe you need to switch these off. There is a second, very-unportable-too-I-guess way: oef2.c: #include stdio.h struct A { char a[3]; int b __attribute__ ((packed)); }; int main(void) { printf(%u\n, (unsigned) sizeof(struct A)); return 0; } This yields: $ gcc -O2 -o oef2 oef2.c $ ./oef2 7 However, unless you are really tight on memory, it is a bad idea to muck around with the default padding in structures, since it degrades performance. If the issue is to write binary files that are portable across different architectures, then padding in structures is only one of the problems you will encounter. Have a look at the C-FAQ-list at URL: http://www.eskimo.com/~scs/C-faq/top.html, item 20.5, for references on how to tackle this problem. HTH, Eric -- E.L. Meijer ([EMAIL PROTECTED]) Eindhoven Univ. of Technology Lab. for Catalysis and Inorg. Chem. (SKA)
Re: Programming question: sizeof struct?
On Fri, 9 Jul 1999, Joop Stakenborg wrote: struct foo { char text[3]; int num; }; sizeof would return 6 and not 5. So it's obvious that the compiler is placing a pad byte between text and num to align num. I want it to stop! That's odd. On most architectures, I would expect sizeof to result in at least 7 because int's are at least four bytes long. It is generally bad form to write code that, like this appears to do, relies upon the rules of packing and alignment. Of course, you didn't write it so you're stuck with it, but such code is generally less portable than doing things another way. Coding up a simple example, I see that, without any options, the sizeof(struct foo) results in 8. Adding the -fpack-struct option, causes the sizeof(struct foo) to result in 7. Adding the line #pragma pack(1) before the definition of the struct causes sizeof(struct foo) to result in 7. This is with what I have installed (it says egcs-2.91.60 on the computer at the house, but I get identical results on an older system running gcc 2.7.2.1) #include stdlib.h #include stdio.h struct foo { char text[3]; int num; }; int main() { printf(sizeof(struct foo) = %d\n, sizeof(struct foo)); return EXIT_SUCCESS; } I believe that, based upon your entire message, there are three possible conclusions that can be reached about your difficulty. 1: You may be using an architecture where the char type (upon which the typedef is based) is two or more bytes long. 2: You may be using a different C compiler than I expect. 3: You may be misinterpreting the output from the compiler. (Suppose struct foo is defined as you give it, but you're actually looking at sizeof(foo) where foo is completely different. That sort of thing can drive you crazy.) -- Jonathan Guthrie ([EMAIL PROTECTED]) Brokersys +281-895-8101 http://www.brokersys.com/ 12703 Veterans Memorial #106, Houston, TX 77014, USA
Re: Programming question: sizeof struct?
Joop Stakenborg [EMAIL PROTECTED] writes: For instance, if the structure were: struct foo { char text[3]; int num; }; sizeof would return 6 and not 5. So it's obvious that the compiler is placing a pad byte between text and num to align num. I want it to stop! Actually thats 8 on alpha. And if you pack that to 5 the program will run with 10% speed and generate a lot of unaligned traps. DON'T do that. Write a parser that can read the data from file in a arch independant manner. If you don't you will get a critical bug as soon as you release the package, because if won't work on different endianess, even if you pack the struct. May the Source be with you. Goswin
Re: Programming question: sizeof struct?
Carl Mummert [EMAIL PROTECTED] writes: #pragma pack(1) struct {}; #pragma pack() Which forces the layout to be as you specified. Using a command line option is a Bad Idea (tm) as it may corrupt glibc's structures To test a resonse to the original message, I made the follwing c file ( I was not familiar with the attribute flag, so I guessed wrong): --begin __attribute__ ((packed)) struct foo struct foo __attribute__ ((packed)) ??? { char c[3]; int x; }; int main() { printf(%d \n, sizeof(struct foo)); } --end ... Which made me think... and check... and sure enough the ORIGINAL STRUCT actually has a size of 7 with the command line option! THe guy is either crazy, or he is using some strange compiler that we don't know about (althoguh he did say the size was 6, as if he had a 286...) Maybe he meant struct foo { char c[3]; short s; // char __PAD; } or struct ofoo { char c[3]; // char __PAD; short } as any normal compiler would generate. MfG, Goswin
Re: Programming question: sizeof struct?
On Sun, 11 Jul 1999, Antti-Juhani Kaijanaho wrote: On Sat, Jul 10, 1999 at 11:26:19PM +1000, Hamish Moffatt wrote: Or even 8, since an int is 32 bits. int can be anything from 16 bits up. we do not have such architectures, i believe In fact, I believe we have architectures where int is 64 bits. well, that is not true either. I believe Linux follows LP64 model on 64bit hw, where long and pointer are 64bits while int is still 32bits Do *not* depend on the size of int! agreed OK
Re: Programming question: sizeof struct?
On Fri, Jul 09, 1999 at 09:44:06AM -0600, Jason Gunthorpe wrote: struct foo { char text[3]; int num; }; sizeof would return 6 and not 5. 6? Are you sure you're using Linux/gcc? Yes, 6, it will insert a single extra character at the end of text to place the alignment of num on a 4 byte boundry. Or even 8, since an int is 32 bits. Hamish -- Hamish Moffatt VK3SB (ex-VK3TYD). CCs of replies from mailing lists are welcome.
Re: Programming question: sizeof struct?
On Sat, Jul 10, 1999 at 11:26:19PM +1000, Hamish Moffatt wrote: Or even 8, since an int is 32 bits. int can be anything from 16 bits up. In fact, I believe we have architectures where int is 64 bits. Do *not* depend on the size of int! -- %%% Antti-Juhani Kaijanaho % [EMAIL PROTECTED] % http://www.iki.fi/gaia/ %%% ... memory leaks are quite acceptable in many applications ... (Bjarne Stroustrup, The Design and Evolution of C++, page 220)
Programming question: sizeof struct?
Hi there, The upstream maintainer of one of my packages is having problems with his code. I thought it would be nice to use the debian mailing lists, to see if we can an answer on this. I will forward any solution to him. -- The reason why I have not released LogConv 1.54 for Linux is that I am having problems with packed structures that is causing some file formats to not be handled properly. Even though I specify -fpack_struct the generated code does not appear to actually do this. Structure fields are offset and the return from sizeof() returns a value that is not valid. For instance, if the structure were: struct foo { char text[3]; int num; }; sizeof would return 6 and not 5. So it's obvious that the compiler is placing a pad byte between text and num to align num. I want it to stop! --- Thanks for your attention. Joop -- Joop Stakenborg PA4TU, ex-PA3ABA [EMAIL PROTECTED] Linux Hamradio Applications and Utilities Homepage http://www.casema.net/~aba
Re: Programming question: sizeof struct?
On Fri, Jul 09, 1999 at 09:09:15AM +0200, Joop Stakenborg wrote: The reason why I have not released LogConv 1.54 for Linux is that I am having problems with packed structures that is causing some file formats to not be handled properly. Reading and writing structs to files is at best unportable, it is generally considered bad design - and it is usually a broken method. When handling binary files you must think of the length of any specific field (int is not necessarily 16 bit or 32 bit or 64 bit, for example!) and you must handle bytesex. These things CANNOT be reliably handled with structs without kluging around. NEVER read/write C data types to/from a binary file. There are exceptions, of course, but they are rare. You should write a reader/writer that treats the file as an octet stream and parses the data from it. So it's obvious that the compiler is placing a pad byte between text and num to align num. I want it to stop! You want your C compiler to compile something other than C. In C, the only guarantee you get is that the struct elements are stored in order (IIRC). -- %%% Antti-Juhani Kaijanaho % [EMAIL PROTECTED] % http://www.iki.fi/gaia/ %%% ... memory leaks are quite acceptable in many applications ... (Bjarne Stroustrup, The Design and Evolution of C++, page 220)
Re: Programming question: sizeof struct?
Hi, Hi there, The upstream maintainer of one of my packages is having problems with his code. with his code? I thought it would be nice to use the debian mailing lists, to see if we can an answer on this. I will forward any solution to him. -- The reason why I have not released LogConv 1.54 for Linux is that I am having problems with packed structures that is causing some file formats to not be handled properly. Even though I specify -fpack_struct the generated code does not appear to actually do this. Structure fields are offset and the return from sizeof() returns a value that is not valid. what do you mean it is not valid? Read ANSI standard or any decent C book. It is quite valid - compiler may insert any padding between struct members... For instance, if the structure were: struct foo { char text[3]; int num; }; sizeof would return 6 and not 5. 6? Are you sure you're using Linux/gcc? The sizeof should be equal to 8 ! It would be 6 only on 16bit platform (MS DOS comes to mind...) So it's obvious that the compiler is placing a pad byte between text and num to align num. I want it to stop! --- Thanks for your attention. Joop from GCC info manual: Specifying Attributes of Variables == The keyword `__attribute__' allows you to specify special attributes of variables or structure fields. This keyword is followed by an attribute specification inside double parentheses. Eight attributes are currently defined for variables: `aligned', `mode', `nocommon', `packed', `section', `transparent_union', `unused', and `weak'. Other attributes are available for functions (*note Function Attributes::.) and for types (*note Type Attributes::.). You may also specify attributes with `__' preceding and following each keyword. This allows you to use them in header files without being concerned about a possible macro of the same name. For example, you may use `__aligned__' instead of `aligned'. ... `packed' The `packed' attribute specifies that a variable or structure field should have the smallest possible alignment--one byte for a variable, and one bit for a field, unless you specify a larger value with the `aligned' attribute. Here is a structure in which the field `x' is packed, so that it immediately follows `a': struct foo { char a; int x[2] __attribute__ ((packed)); }; But i advise to use gcc default padding - it is definitely more efficient and portable... IMO, you have problems with structs I/O. The UNIX paradigm is that files have no structure, they're just byte streams... And in order to be endian-neutral, choose some byte ordering - for example, lets keep network byte ordering in the file Provide two small functions like write_struct_foo( int fd, const struct foo* ptr ) { int tmp = htonl( ptr-num ); write( fd, ptr-name, 3 ); write( fd, tmp, sizeof(int) ); } read_struct_foo( int fd, struct foo* ptr ) { int tmp; read( fd, ptr-name, 3 ); read( fd, tmp, sizeof(int) ); ptr-num = ntohl( tmp ); } Of course, error checking and other stuff should be added but hope you got the idea. Just in case, some info from glibc doc: Byte Order Conversion - Different kinds of computers use different conventions for the ordering of bytes within a word. Some computers put the most significant byte within a word first (this is called big-endian order), and others put it last (little-endian order). So that machines with different byte order conventions can communicate, the Internet protocols specify a canonical byte order convention for data transmitted over the network. This is known as the network byte order. When establishing an Internet socket connection, you must make sure that the data in the `sin_port' and `sin_addr' members of the `sockaddr_in' structure are represented in the network byte order. If you are encoding integer data in the messages sent through the socket, you should convert this to network byte order too. If you don't do this, your program may fail when running on or talking to other kinds of machines. If you use `getservbyname' and `gethostbyname' or `inet_addr' to get the port number and host address, the values are already in the network byte order, and you can copy them directly into the `sockaddr_in' structure. Otherwise, you have to convert the values explicitly. Use `htons' and `ntohs' to convert values for the `sin_port' member. Use `htonl' and `ntohl' to convert IPv4 addresses for the `sin_addr' member. (Remember, `struct in_addr' is equivalent to `uint32_t'.) These functions are declared in `netinet/in.h'. - Function: uint16_t htons (uint16_t HOSTSHORT) This function converts the `uint16_t' integer
Re: Programming question: sizeof struct?
On Fri, 9 Jul 1999, Oleg Krivosheev wrote: to not be handled properly. Even though I specify -fpack_struct the generated code does not appear to actually do this. Structure fields are offset and the return from sizeof() returns a value that is not valid. what do you mean it is not valid? Read ANSI standard or any decent C book. It is quite valid - compiler may insert any padding between struct members... He probably means it is not exactly what he wants : For instance, if the structure were: struct foo { char text[3]; int num; }; sizeof would return 6 and not 5. 6? Are you sure you're using Linux/gcc? Yes, 6, it will insert a single extra character at the end of text to place the alignment of num on a 4 byte boundry. So it's obvious that the compiler is placing a pad byte between text and num to align num. I want it to stop! I always hated gcc __attribute__, I prefer the simpler and more common #pragma pack(1) struct {}; #pragma pack() Which forces the layout to be as you specified. Using a command line option is a Bad Idea (tm) as it may corrupt glibc's structures Jason
Re: Programming question: sizeof struct?
Hi, On Fri, 9 Jul 1999, Jason Gunthorpe wrote: On Fri, 9 Jul 1999, Oleg Krivosheev wrote: to not be handled properly. Even though I specify -fpack_struct the generated code does not appear to actually do this. Structure fields are offset and the return from sizeof() returns a value that is not valid. what do you mean it is not valid? Read ANSI standard or any decent C book. It is quite valid - compiler may insert any padding between struct members... He probably means it is not exactly what he wants : For instance, if the structure were: struct foo { char text[3]; int num; }; sizeof would return 6 and not 5. 6? Are you sure you're using Linux/gcc? Yes, 6, it will insert a single extra character at the end of text to place the alignment of num on a 4 byte boundry. Once again, sizeof(int) = 4 on Linux/ia32 and Linux/SPARC (that is what i can check), sizeof(text) is at least 3, therefore sizeof( struct foo ) should be at least 7 !!! With additional padding byte sizeof would be equal to 8. What platform/OS/compiler are you using? So it's obvious that the compiler is placing a pad byte between text and num to align num. I want it to stop! I always hated gcc __attribute__, I prefer the simpler and more common #pragma pack(1) struct {}; #pragma pack() Which forces the layout to be as you specified. i got an impression it doesn't work for the code... if i misinterpreted the original message, i'm sorry Using a command line option is a Bad Idea (tm) as it may corrupt glibc's structures Attributes have nothing in common with command line switches, they're just like pragmas From gcc info: The keyword `__attribute__' allows you to specify special attributes of variables or structure fields. Jason Anyway, i think better redesign and rewrite struct I/O stuff. pragma pack and __attribute__ is just gross hack OK
Re: Programming question: sizeof struct?
#pragma pack(1) struct {}; #pragma pack() Which forces the layout to be as you specified. Using a command line option is a Bad Idea (tm) as it may corrupt glibc's structures To test a resonse to the original message, I made the follwing c file ( I was not familiar with the attribute flag, so I guessed wrong): --begin __attribute__ ((packed)) struct foo { char c[3]; int x; }; int main() { printf(%d \n, sizeof(struct foo)); } --end This has a size of 8 without the command-line option, but 7 with it. But this has 7 with or without: struct foo { char c[3]; int x __attribute__ ((packed)); }; And this has 7 with or without #pragma pack(1) struct foo { char c[3]; int x; }; #pragma pack() Which made me think... and check... and sure enough the ORIGINAL STRUCT actually has a size of 7 with the command line option! THe guy is either crazy, or he is using some strange compiler that we don't know about (althoguh he did say the size was 6, as if he had a 286...) Carl
Re: Programming question: sizeof struct?
%% Jason Gunthorpe [EMAIL PROTECTED] writes: For instance, if the structure were: struct foo { char text[3]; int num; }; sizeof would return 6 and not 5. 6? Are you sure you're using Linux/gcc? jg Yes, 6, it will insert a single extra character at the end of text to jg place the alignment of num on a 4 byte boundry. Yes, so 4 bytes for the array and... how many for the int? Right :). So it's obvious that the compiler is placing a pad byte between text and num to align num. I want it to stop! jg I always hated gcc __attribute__, I prefer the simpler and more common jg #pragma pack(1) jg struct {}; jg #pragma pack() Ugh. #pragma is terrible. See the GCC manual for a description of why. __attribute__ may be verbose but it's _much_ better than #pragma. -- --- Paul D. Smith [EMAIL PROTECTED] Network Management Development Please remain calm...I may be mad, but I am a professional. --Mad Scientist --- These are my opinions---Nortel Networks takes no responsibility for them.