2

I am trying the following, with gcc on win32.

#include <stdio.h>

struct st { char c; int x; } __attribute__ ((packed));

int main() {
    printf("%d\n", sizeof(struct st));
    return 0;
}

I would expect that the printed value is 5, but it's 8.

With the following, however, I get 5.

#include <stdio.h>

#pragma pack(1)
struct st { char c; int x; };

int main() {
    printf("%d\n", sizeof(struct st));
    return 0;
}

There must be something wrong in my program, but I can't see what. I have read gcc's manual and several questions on SO about this, and I'm still puzzled. Any hint?

Also from the answers to these questions on SO, I understand that I should not use packed structs for marshalling, and I probably won't use it much, but I still would like to understand what I'm not able to see in such a short program.

Note: the problem occurs with both gcc-4.9.2 and gcc-4.8.4.

Nivak
  • 21
  • 4
  • 2
    For me it works. http://codepad.org/Zrilgx9t – Jayesh Bhoi Jan 08 '15 at 11:54
  • @Jayesh Ok, then, I have gcc-4.9.2 from [mingw-w64](http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/4.9.2/), maybe it's a problem with this build? – Nivak Jan 08 '15 at 11:58
  • first, you should write %lu instead of %d – yakoudbz Jan 08 '15 at 11:59
  • @yakoudbz This will throw a warning when compiling: `warning: format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'unsigned int'`. However, I agree that %d should be replaced by %u. Of course, it does not solve the problem either. – Nivak Jan 08 '15 at 12:02
  • @Nivak May or may not. But you look for it here https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991 – Jayesh Bhoi Jan 08 '15 at 12:03
  • @Jayesh Now I make it work (print 5) with `((gcc_struct, packed))` (from the link you give), and it fails (print 8) with `((ms_struct, packed))`. I absolutely don't know why or how! It seems to be a bug in gcc, starting from version 4.7.0 - or maybe it was patched at some point and the bug showed up in version 4.9.2. Anyway, thank you! – Nivak Jan 08 '15 at 12:11
  • @Nivak, size_t a unsigned long int on my machine, I thought it was the same everywhere... It's apparently guaranteed to be an unsigned integer able to hold any array index, but there is no fixed length except it must be at least 16 bits. The size of size_t is defined in stddef.h – yakoudbz Jan 10 '15 at 22:46

2 Answers2

2

You have the attribute in the wrong place - try this:

struct st { char c;
            int x __attribute__ ((packed));
          };

As per the example in the gcc manual, this will cause x to be packed such that it immediately follows c.

Of course you shouldn't really be doing this in the first place, as your code will break on certain architectures, and even where it doesn't break there may be performance penalties.

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • OP's code works for me so placing the `__attribute__ ((packed))` at the end should be fine – Gopi Jan 08 '15 at 11:59
  • @Gopi, I'm not sure about that: 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. – David Ranieri Jan 08 '15 at 12:01
  • @AlterMann and @PaulR According to all I have found on the net, it should work after the struct (or even before, as in `struct __attribute__ ((packed)) st { char c; int x; };`). But see Jayesh's comment above, I think it's a bug. – Nivak Jan 08 '15 at 12:12
  • @PaulR I would only have used this for marshalling, but looking for an answer I have found that actually even for this I shouldn't... I'm fine with this, but I wanted to understand how this attribute works, just in case. – Nivak Jan 08 '15 at 12:16
  • The packed attribute can be placed on variables or struct fields, documented here: https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html#Variable-Attributes or it can be placed on structs, documented here: https://gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html . – nos Jan 09 '15 at 08:49
0

Working fine on my environment Centos 5.11 (64bit) prints 5 for the first case you mentioned.

gcc version 4.9.1 (GCC)

gcc file.c

./a.out 

5

theadnangondal
  • 1,546
  • 3
  • 14
  • 28
  • According to Jayesh's [link above](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52991), it's a problem with mingw. I reproduce the same problem with gcc-4.8.4 or gcc-4.9.2 both in [32](http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/) and [64 bits](http://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/), using mingw-w64. Thanks anyway for your answer. – Nivak Jan 09 '15 at 20:38