I am not looking to improve performance or memory usage, this question was purely sparked from curiosity.
Main Question
Given the following class will the C# compiler (Mono + .NET) pack the two short
variables into 4 bytes or will they consume 8 bytes (with alignment)?
public class SomeClass {
short a;
short b;
}
Secondary Question
If the answer to the above question was not 4 bytes, would the following alternative offer any advantages (where SomeClass
is used in very large quantities):
// Warning, my bit math might not be entirely accurate!
public class SomeClass {
private int _ab;
public short a {
get { return _ab & 0x00ff; }
set { _ab |= value & 0x00ff;
}
public short b {
get { return _ab >> 8; }
set { _ab |= value << 8; }
}
}
Generally, the smallest addressable chunk of data in C is a byte. You can not have a pointer to a bit, so you can not declare a variable of 1 bit size.
When a structure is packed, these paddings are not inserted. The compiler has to generate more code (which runs slower) to extract the non-aligned data members, and also to write to them.
Structure Padding in C:The structure padding is automatically done by the compiler to make sure all its members are byte aligned. Here 'char' is only 1 byte but after 3 byte padding, the number starts at 4 byte boundary. For 'int' and 'double', it takes up 4 and 8 bytes respectively.
Structure padding is a concept in C that adds the one or more empty bytes between the memory addresses to align the data in memory. Let's first understand the structure padding in C through a simple scenario which is given below: Suppose we create a user-defined structure.
It depends on the runtime, as @David_M says, but you can force it by using the [StructLayout]
attribute which has a Pack
member which you can use to control packing. Alternatively you can use [FieldOffset]
to manually lay out a struct's members (even overlap, which is how you implement unions in .NET).
This depends on the runtime, not the compiler. You can override the default behavior with [StructLayout]
, which can help - though the default behavior should be fine.
That being said, if minimzing total size is an absolute requirement, you may want to consider a struct
instead of a class
. When using a class, each instance of the class is going to add significant overhead. Between the syncblk, TypeHandle, etc, as well as the reference (which on a 64bit system is another 8 bytes) object instance uses a fair amount of "extra" memory above and beyond your two shorts. For details, see "How the CLR Creates Runtime Objects".
Storing your data packed into a collection of value types can avoid this entirely, and keep the instances down to 8 bytes each total (plus the collection overhead). Of couse, this changes the semantics in terms of usage, but if you're only using two shorts, this will reduce the amount of overhead involved in your type, especially on 64bit systems.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With