Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are small data types packed in C#

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; }
    }
}
like image 564
Lea Hayes Avatar asked Jun 21 '12 14:06

Lea Hayes


People also ask

What is the smallest data type in C?

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.

What is a packed structure in C?

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.

How does padding work in C?

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.

What is structure padding and packing in C?

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.


2 Answers

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).

like image 70
Dai Avatar answered Oct 12 '22 12:10

Dai


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.

like image 38
Reed Copsey Avatar answered Oct 12 '22 11:10

Reed Copsey