If i define a char variable
char a;
and a structure with a single char member
struct OneChar {
char a;
};
<
Various compilers will optimize to add padding between or at the end of the struct. So, it's not safe on all compilers or platforms to assume the allocated size is what it seems. Check your compiler options for setting struct padding.
For instance, Visual Studio uses the #pragma pack directive to override default optimizations.
As long as there's a single member, I think you're safe with the assumption.
When you take the size of a struct, it includes the padding bytes. But, if you have something like the following:
void fun()
{
char c;
int n;
}
The compiler is free to insert padding for whatever reason it sees. So, the padding could be there in case of standalone variables, you just can't know about that like in the case of a struct.
It depends on the architecture and the compiler. For this particular case you should be safe, but check out Data Structure Padding.
Here's an excerpt:
Typical alignment of C structs on x86
Data structure members are stored sequentially in a memory so that in the structure below the member Data1 will always precede Data2 and Data2 will always precede Data3:
struct MyData { short Data1; short Data2; short Data3; };
If the type "short" is stored in two bytes of memory then each member of the data structure depicted above would be 2-byte aligned. Data1 would be at offset 0, Data2 at offset 2 and Data3 at offset 4. The size of this structure would be 6 bytes.
The type of each member of the structure usually has a default alignment, meaning that it will, unless otherwise requested by the programmer, be aligned on a pre-determined boundary. The following typical alignments are valid for compilers from Microsoft, Borland, and GNU when compiling for 32-bit x86:
- A char (one byte) will be 1-byte aligned.
- A short (two bytes) will be 2-byte aligned.
- An int (four bytes) will be 4-byte aligned.
- A float (four bytes) will be 4-byte aligned.
- A double (eight bytes) will be 8-byte aligned on Windows and 4-byte aligned on Linux.
Here is a structure with members of various types, totaling 8 bytes before compilation:
struct MixedData { char Data1; short Data2; int Data3; char Data4; };
After compilation the data structure will be supplemented with padding bytes to ensure a proper alignment for each of its members:
struct MixedData /* after compilation */ { char Data1; char Padding0[1]; /* For the following 'short' to be aligned on a 2 byte boundary */ short Data2; int Data3; char Data4; char Padding1[3]; };
The compiled size of the structure is now 12 bytes. It is important to note that the last member is padded with the number of bytes required to conform to the largest type of the structure. In this case 3 bytes are added to the last member to pad the structure to the size of a long word.
It is possible to change the alignment of structures to reduce the memory they require (or to conform to an existing format) by changing the compiler’s alignment (or “packing”) of structure members.
Requesting that the MixedData structure above be aligned to a one byte boundary will have the compiler discard the pre-determined alignment of the members and no padding bytes would be inserted.
While there is no standard way of defining the alignment of structure members, some compilers use #pragma directives to specify packing inside source files. Here is an example:
#pragma pack(push) /* push current alignment to stack */ #pragma pack(1) /* set alignment to 1 byte boundary */ struct MyPackedData { char Data1; long Data2; char Data3; }; #pragma pack(pop) /* restore original alignment from stack */
This structure would have a compiled size of 6 bytes. The above directives are available in compilers from Microsoft, Borland, GNU and many others.
The case you list will be packed as a 1-byte structure under all ABIs I am aware of.
But if you need to portably handle more complicated cases, best practice is to always use sizeof(struct OneChar)
when computing memory sizes, and taking the offset of the field address when you need to compute addresses via a trick like:
(char*)&(((struct OneChar*)0)->a) - (char*)0
All a
s will have the same size, no matter if they stand alone or are inside a structure.
What may happen inside a structure is that there is padding between members ... but that may also happen in "stand alone" variables.