How to organize members in a struct to waste least space on alignment?Are there performance issues when using pragma pack(1)?Why isn't sizeof for a struct equal to the sum of sizeof of each member?new[] expression does not respect alignment in Microsoft VC++Why can't C compilers rearrange struct members to eliminate alignment padding?Memory layout mismatching between CPU and GPU code with CUDAC++ struct aligment to 1 byte causes crash on WinCEIs there a way to guarantee alignment of members of a malloc()-ed structsHow does CUDA's nppiMalloc… function guarantee alignment?Optimally packing a recursively templated struct without loss of alignmentR_alloc and alignment considerationsHow does aligning memory in a custom double ended stack-based allocator work?

Was it really unprofessional of me to leave without asking for a raise first?

How can my story take place on Earth without referring to our existing cities and countries?

Movie in a trailer park named Paradise and a boy playing a video game then being recruited by aliens to fight in space

How can I deal with extreme temperatures in a hotel room?

Meaning of じゃないんじゃない?

Is it bad to describe a character long after their introduction?

For decoupling an IC's power supply pins, is there any reason to use multiple capacitances when all the MLCCs have the same package size?

Ordered list of OR journals

Who are these Discworld wizards from this picture?

Different budgets within roommate group

How did researchers find articles before the Internet and the computer era?

Losing queen and then winning the game

Should I report a leak of confidential HR information?

Why does the same classical piece sound like it's in a different key in different recordings?

What exactly did Ant-Man see that made him say that their plan worked?

What does grep -v "grep" mean and do?

Sharing referee/AE report online to point out a grievous error in refereeing

Golf the smallest circle!

Who voices the character "Finger" in The Fifth Element?

What's the safest way to inform a new user of their password on an invite-only website?

Why were the first airplanes "backwards"?

How is this practical and very old scene shot?

Do launching rockets produce a sonic boom?

Step into the Octagram



How to organize members in a struct to waste least space on alignment?


Are there performance issues when using pragma pack(1)?Why isn't sizeof for a struct equal to the sum of sizeof of each member?new[] expression does not respect alignment in Microsoft VC++Why can't C compilers rearrange struct members to eliminate alignment padding?Memory layout mismatching between CPU and GPU code with CUDAC++ struct aligment to 1 byte causes crash on WinCEIs there a way to guarantee alignment of members of a malloc()-ed structsHow does CUDA's nppiMalloc… function guarantee alignment?Optimally packing a recursively templated struct without loss of alignmentR_alloc and alignment considerationsHow does aligning memory in a custom double ended stack-based allocator work?






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








11















I have just realized how much memory is wasted as a result of alignment in C++. Consider the following simple example:



struct X

int a;
double b;
int c;
;

int main()

cout << "sizeof(int) = " << sizeof(int) << 'n';
cout << "sizeof(double) = " << sizeof(double) << 'n';
cout << "2 * sizeof(int) + sizeof(double) = " << 2 * sizeof(int) + sizeof(double) << 'n';
cout << "but sizeof(X) = " << sizeof(X) << 'n';



When using g++ the program gives the following output:



sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 24


That's 50% memory overhead! In a 3-gigabyte array of 134'217'728 Xs 1 gigabyte would be pure padding.



Fortunately, the solution to the problem is very simple - we simply have to swap double b and int c around:



struct X

int a;
int c;
double b;
;


Now the result is much more satisfying:



sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 16


There is however a problem: this isn't cross-compatible. Yes, under g++ an int is 4 bytes and a double is 8 bytes, but that's not necessarily always true (their alignment doesn't have to be the same either), so under a different environment this "fix" could not only be useless, but could also potentially make things worse by increasing the amount of padding needed.



Is there a reliable cross-platform way to solve this problem (minimize the amount of needed padding without suffering from decreased performance caused by misalignment)? Why doesn't the compiler perform such optimizations (swap struct/class members around to decrease padding)?



EDIT



Due to misunderstanding and confusion, I'd like to emphasize that I don't want to "pack" my struct. I still want it to be aligned, but in a way that uses the least memory on padding.










share|improve this question
























  • If you need "arrays" of hundreds of millions of elements, then perhaps arrays is not the correct data-structure to begin with? At least not in-memory arrays (think memory mapped files, or perhaps even some kind of database)?

    – Some programmer dude
    9 hours ago












  • And really, the only possible answer to the question "[i]s there a reliable cross-platform way to solve this problem (minimize the amount of needed padding without suffering from decreased performance caused by misalignment)?" could only be a simple "no". There are probably compiler and system specific ways to work around it, but nothing truly portable or compiler/platform/system agnostic.

    – Some programmer dude
    9 hours ago







  • 1





    May be some portability benefits from using fixed width integers so they don't change size on you.

    – user4581301
    9 hours ago






  • 3





    largest alignment requirements first. If none, then largest members first. Regarding your real question, yes there is a cross-compatible method for doing this: it's called a string. Outside of that, types using specified bit widths can help significantly, but still require endian handling if you're really serious about cross platform. In short, protocols exist specifically to address such issues and bridge the hard differences between platforms. Things like this are one of many reasons why they exist, Caveat: Good chance I completely misunderstood the "this" of this question.

    – WhozCraig
    9 hours ago







  • 1





    For all the reasons above, there is no one thing that guarantees a minimum storage for struct size, but @WhozCraig provides a precise explanation of the oversimplified rule Biggest First, Smallest Last in decreasing order of storage size required. That's about as reasonable an approach likely to minimize storage across compilers and hardware, but there is no guarantee any two structs will be allocated the same amount of storage between compilers (other than trivial examples (such as struct foo int a, b; ;)

    – David C. Rankin
    8 hours ago


















11















I have just realized how much memory is wasted as a result of alignment in C++. Consider the following simple example:



struct X

int a;
double b;
int c;
;

int main()

cout << "sizeof(int) = " << sizeof(int) << 'n';
cout << "sizeof(double) = " << sizeof(double) << 'n';
cout << "2 * sizeof(int) + sizeof(double) = " << 2 * sizeof(int) + sizeof(double) << 'n';
cout << "but sizeof(X) = " << sizeof(X) << 'n';



When using g++ the program gives the following output:



sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 24


That's 50% memory overhead! In a 3-gigabyte array of 134'217'728 Xs 1 gigabyte would be pure padding.



Fortunately, the solution to the problem is very simple - we simply have to swap double b and int c around:



struct X

int a;
int c;
double b;
;


Now the result is much more satisfying:



sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 16


There is however a problem: this isn't cross-compatible. Yes, under g++ an int is 4 bytes and a double is 8 bytes, but that's not necessarily always true (their alignment doesn't have to be the same either), so under a different environment this "fix" could not only be useless, but could also potentially make things worse by increasing the amount of padding needed.



Is there a reliable cross-platform way to solve this problem (minimize the amount of needed padding without suffering from decreased performance caused by misalignment)? Why doesn't the compiler perform such optimizations (swap struct/class members around to decrease padding)?



EDIT



Due to misunderstanding and confusion, I'd like to emphasize that I don't want to "pack" my struct. I still want it to be aligned, but in a way that uses the least memory on padding.










share|improve this question
























  • If you need "arrays" of hundreds of millions of elements, then perhaps arrays is not the correct data-structure to begin with? At least not in-memory arrays (think memory mapped files, or perhaps even some kind of database)?

    – Some programmer dude
    9 hours ago












  • And really, the only possible answer to the question "[i]s there a reliable cross-platform way to solve this problem (minimize the amount of needed padding without suffering from decreased performance caused by misalignment)?" could only be a simple "no". There are probably compiler and system specific ways to work around it, but nothing truly portable or compiler/platform/system agnostic.

    – Some programmer dude
    9 hours ago







  • 1





    May be some portability benefits from using fixed width integers so they don't change size on you.

    – user4581301
    9 hours ago






  • 3





    largest alignment requirements first. If none, then largest members first. Regarding your real question, yes there is a cross-compatible method for doing this: it's called a string. Outside of that, types using specified bit widths can help significantly, but still require endian handling if you're really serious about cross platform. In short, protocols exist specifically to address such issues and bridge the hard differences between platforms. Things like this are one of many reasons why they exist, Caveat: Good chance I completely misunderstood the "this" of this question.

    – WhozCraig
    9 hours ago







  • 1





    For all the reasons above, there is no one thing that guarantees a minimum storage for struct size, but @WhozCraig provides a precise explanation of the oversimplified rule Biggest First, Smallest Last in decreasing order of storage size required. That's about as reasonable an approach likely to minimize storage across compilers and hardware, but there is no guarantee any two structs will be allocated the same amount of storage between compilers (other than trivial examples (such as struct foo int a, b; ;)

    – David C. Rankin
    8 hours ago














11












11








11


1






I have just realized how much memory is wasted as a result of alignment in C++. Consider the following simple example:



struct X

int a;
double b;
int c;
;

int main()

cout << "sizeof(int) = " << sizeof(int) << 'n';
cout << "sizeof(double) = " << sizeof(double) << 'n';
cout << "2 * sizeof(int) + sizeof(double) = " << 2 * sizeof(int) + sizeof(double) << 'n';
cout << "but sizeof(X) = " << sizeof(X) << 'n';



When using g++ the program gives the following output:



sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 24


That's 50% memory overhead! In a 3-gigabyte array of 134'217'728 Xs 1 gigabyte would be pure padding.



Fortunately, the solution to the problem is very simple - we simply have to swap double b and int c around:



struct X

int a;
int c;
double b;
;


Now the result is much more satisfying:



sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 16


There is however a problem: this isn't cross-compatible. Yes, under g++ an int is 4 bytes and a double is 8 bytes, but that's not necessarily always true (their alignment doesn't have to be the same either), so under a different environment this "fix" could not only be useless, but could also potentially make things worse by increasing the amount of padding needed.



Is there a reliable cross-platform way to solve this problem (minimize the amount of needed padding without suffering from decreased performance caused by misalignment)? Why doesn't the compiler perform such optimizations (swap struct/class members around to decrease padding)?



EDIT



Due to misunderstanding and confusion, I'd like to emphasize that I don't want to "pack" my struct. I still want it to be aligned, but in a way that uses the least memory on padding.










share|improve this question
















I have just realized how much memory is wasted as a result of alignment in C++. Consider the following simple example:



struct X

int a;
double b;
int c;
;

int main()

cout << "sizeof(int) = " << sizeof(int) << 'n';
cout << "sizeof(double) = " << sizeof(double) << 'n';
cout << "2 * sizeof(int) + sizeof(double) = " << 2 * sizeof(int) + sizeof(double) << 'n';
cout << "but sizeof(X) = " << sizeof(X) << 'n';



When using g++ the program gives the following output:



sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 24


That's 50% memory overhead! In a 3-gigabyte array of 134'217'728 Xs 1 gigabyte would be pure padding.



Fortunately, the solution to the problem is very simple - we simply have to swap double b and int c around:



struct X

int a;
int c;
double b;
;


Now the result is much more satisfying:



sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 16


There is however a problem: this isn't cross-compatible. Yes, under g++ an int is 4 bytes and a double is 8 bytes, but that's not necessarily always true (their alignment doesn't have to be the same either), so under a different environment this "fix" could not only be useless, but could also potentially make things worse by increasing the amount of padding needed.



Is there a reliable cross-platform way to solve this problem (minimize the amount of needed padding without suffering from decreased performance caused by misalignment)? Why doesn't the compiler perform such optimizations (swap struct/class members around to decrease padding)?



EDIT



Due to misunderstanding and confusion, I'd like to emphasize that I don't want to "pack" my struct. I still want it to be aligned, but in a way that uses the least memory on padding.







c++ optimization memory-alignment memory-layout struct-member-alignment






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 9 hours ago









NathanOliver

106k19 gold badges159 silver badges235 bronze badges




106k19 gold badges159 silver badges235 bronze badges










asked 9 hours ago









Yan B.Yan B.

35112 bronze badges




35112 bronze badges












  • If you need "arrays" of hundreds of millions of elements, then perhaps arrays is not the correct data-structure to begin with? At least not in-memory arrays (think memory mapped files, or perhaps even some kind of database)?

    – Some programmer dude
    9 hours ago












  • And really, the only possible answer to the question "[i]s there a reliable cross-platform way to solve this problem (minimize the amount of needed padding without suffering from decreased performance caused by misalignment)?" could only be a simple "no". There are probably compiler and system specific ways to work around it, but nothing truly portable or compiler/platform/system agnostic.

    – Some programmer dude
    9 hours ago







  • 1





    May be some portability benefits from using fixed width integers so they don't change size on you.

    – user4581301
    9 hours ago






  • 3





    largest alignment requirements first. If none, then largest members first. Regarding your real question, yes there is a cross-compatible method for doing this: it's called a string. Outside of that, types using specified bit widths can help significantly, but still require endian handling if you're really serious about cross platform. In short, protocols exist specifically to address such issues and bridge the hard differences between platforms. Things like this are one of many reasons why they exist, Caveat: Good chance I completely misunderstood the "this" of this question.

    – WhozCraig
    9 hours ago







  • 1





    For all the reasons above, there is no one thing that guarantees a minimum storage for struct size, but @WhozCraig provides a precise explanation of the oversimplified rule Biggest First, Smallest Last in decreasing order of storage size required. That's about as reasonable an approach likely to minimize storage across compilers and hardware, but there is no guarantee any two structs will be allocated the same amount of storage between compilers (other than trivial examples (such as struct foo int a, b; ;)

    – David C. Rankin
    8 hours ago


















  • If you need "arrays" of hundreds of millions of elements, then perhaps arrays is not the correct data-structure to begin with? At least not in-memory arrays (think memory mapped files, or perhaps even some kind of database)?

    – Some programmer dude
    9 hours ago












  • And really, the only possible answer to the question "[i]s there a reliable cross-platform way to solve this problem (minimize the amount of needed padding without suffering from decreased performance caused by misalignment)?" could only be a simple "no". There are probably compiler and system specific ways to work around it, but nothing truly portable or compiler/platform/system agnostic.

    – Some programmer dude
    9 hours ago







  • 1





    May be some portability benefits from using fixed width integers so they don't change size on you.

    – user4581301
    9 hours ago






  • 3





    largest alignment requirements first. If none, then largest members first. Regarding your real question, yes there is a cross-compatible method for doing this: it's called a string. Outside of that, types using specified bit widths can help significantly, but still require endian handling if you're really serious about cross platform. In short, protocols exist specifically to address such issues and bridge the hard differences between platforms. Things like this are one of many reasons why they exist, Caveat: Good chance I completely misunderstood the "this" of this question.

    – WhozCraig
    9 hours ago







  • 1





    For all the reasons above, there is no one thing that guarantees a minimum storage for struct size, but @WhozCraig provides a precise explanation of the oversimplified rule Biggest First, Smallest Last in decreasing order of storage size required. That's about as reasonable an approach likely to minimize storage across compilers and hardware, but there is no guarantee any two structs will be allocated the same amount of storage between compilers (other than trivial examples (such as struct foo int a, b; ;)

    – David C. Rankin
    8 hours ago

















If you need "arrays" of hundreds of millions of elements, then perhaps arrays is not the correct data-structure to begin with? At least not in-memory arrays (think memory mapped files, or perhaps even some kind of database)?

– Some programmer dude
9 hours ago






If you need "arrays" of hundreds of millions of elements, then perhaps arrays is not the correct data-structure to begin with? At least not in-memory arrays (think memory mapped files, or perhaps even some kind of database)?

– Some programmer dude
9 hours ago














And really, the only possible answer to the question "[i]s there a reliable cross-platform way to solve this problem (minimize the amount of needed padding without suffering from decreased performance caused by misalignment)?" could only be a simple "no". There are probably compiler and system specific ways to work around it, but nothing truly portable or compiler/platform/system agnostic.

– Some programmer dude
9 hours ago






And really, the only possible answer to the question "[i]s there a reliable cross-platform way to solve this problem (minimize the amount of needed padding without suffering from decreased performance caused by misalignment)?" could only be a simple "no". There are probably compiler and system specific ways to work around it, but nothing truly portable or compiler/platform/system agnostic.

– Some programmer dude
9 hours ago





1




1





May be some portability benefits from using fixed width integers so they don't change size on you.

– user4581301
9 hours ago





May be some portability benefits from using fixed width integers so they don't change size on you.

– user4581301
9 hours ago




3




3





largest alignment requirements first. If none, then largest members first. Regarding your real question, yes there is a cross-compatible method for doing this: it's called a string. Outside of that, types using specified bit widths can help significantly, but still require endian handling if you're really serious about cross platform. In short, protocols exist specifically to address such issues and bridge the hard differences between platforms. Things like this are one of many reasons why they exist, Caveat: Good chance I completely misunderstood the "this" of this question.

– WhozCraig
9 hours ago






largest alignment requirements first. If none, then largest members first. Regarding your real question, yes there is a cross-compatible method for doing this: it's called a string. Outside of that, types using specified bit widths can help significantly, but still require endian handling if you're really serious about cross platform. In short, protocols exist specifically to address such issues and bridge the hard differences between platforms. Things like this are one of many reasons why they exist, Caveat: Good chance I completely misunderstood the "this" of this question.

– WhozCraig
9 hours ago





1




1





For all the reasons above, there is no one thing that guarantees a minimum storage for struct size, but @WhozCraig provides a precise explanation of the oversimplified rule Biggest First, Smallest Last in decreasing order of storage size required. That's about as reasonable an approach likely to minimize storage across compilers and hardware, but there is no guarantee any two structs will be allocated the same amount of storage between compilers (other than trivial examples (such as struct foo int a, b; ;)

– David C. Rankin
8 hours ago






For all the reasons above, there is no one thing that guarantees a minimum storage for struct size, but @WhozCraig provides a precise explanation of the oversimplified rule Biggest First, Smallest Last in decreasing order of storage size required. That's about as reasonable an approach likely to minimize storage across compilers and hardware, but there is no guarantee any two structs will be allocated the same amount of storage between compilers (other than trivial examples (such as struct foo int a, b; ;)

– David C. Rankin
8 hours ago













4 Answers
4






active

oldest

votes


















5














gcc has the -Wpadded warning that warns when padding is added to a structure:



https://godbolt.org/z/iwO5Q3:



<source>:4:12: warning: padding struct to align 'X::b' [-Wpadded]
4 | double b;
| ^

<source>:1:8: warning: padding struct size to alignment boundary [-Wpadded]
1 | struct X
| ^


And you can manually rearrange members so that there is less / no padding. But this is not a cross platform solution, as different types can have different sizes / alignments on different system (Most notably pointers being 4 or 8 bytes on different architectures). The general rule of thumb is go from largest to smallest alignment when declaring members, and if you're still worried, compile your code with -Wpadded once (But I wouldn't keep it on generally, because padding is necessary sometimes).



As for the reason why the compiler can't do it automatically is because of the standard ([class.mem]/19). It guarantees that, because this is a simple struct with only public members, &x.a < &x.c (for some X x;), so they can't be rearranged.






share|improve this answer




















  • 1





    I honestly didn't think I'd see something useful come out of this question. Wasn't aware of that gcc option (and now I'm hopign clang has it as well). Thanks for teaching me something. tick.

    – WhozCraig
    9 hours ago


















5














There really isn't a portable solution in the generic case. Baring minimal requirements the standard imposes, types can be any size the implementation wants to make them.



To go along with that, The compiler is not allowed to reorder class member to make it more efficient. The standard mandates that the objects must be laid out in their declared order (by access modifier), so that's out as well.



You can use fixed width types like



struct foo

int64_t a;
int16_t b;
int8_t c;
int8_t d;
;


and this will be the same on all platforms, provided they supply those types, but it only works with integer types. There are no fixed width floating point types and many standard objects/containers can be different sizes on different platforms.






share|improve this answer

























  • Adding salt to the wound, floating point types are frequently hyper sensitive to bus-alignment positions, thereby enhancing the no-silver-bullet mantra. Regardless, this is very useful when loading up structs with anything other than floating point and potentially pointers. I use it frequently.

    – WhozCraig
    9 hours ago











  • Why isn’t member rearrangement allowed? Could you clarify?

    – Yan B.
    9 hours ago






  • 2





    If you take the cross-platform portability to the limit, note that these "exact width" types are optional. Every platform must have int_least16_t and int_fast16_t, but (for example if CHAR_BIT != 8), int16_t need not exist on a given platform.

    – DevSolar
    9 hours ago











  • @DevSolar While they are optional, the code will fail to compile if they are not present so at least you wont get binary that blows up on you.

    – NathanOliver
    9 hours ago






  • 1





    @YanB. It is mandated by the standard. see: eel.is/c++draft/class.mem#19

    – NathanOliver
    9 hours ago


















0














You can use #pragma pack(1), but the very reason of this is that the compiler optimizes. Accessing a variable through the full register is faster than accessing it to the least bit.



Specific packing is only useful for serialization and intercompiler compatibility, etc.



As NathanOliver correctly added, this might even fail on some platforms.






share|improve this answer




















  • 3





    May want to note this carries potential performance issues or may cause the code to not work on some platforms: stackoverflow.com/questions/7793511/…

    – NathanOliver
    9 hours ago






  • 1





    To my knowledge, using #pragma pack causes potential performance issues and as such is not the desired solution.

    – Yan B.
    9 hours ago


















0














Well, maybe I'm cooking the concept wrong, but you can use std::aligned_storage to allocate your data. Applied to the struct, considered above, it could be something like that:



#include <type_traits>
#include <iostream>
#include <algorithm>

struct X

int a;
double b;
int c;
;


int main()

const std::size_t TOTAL_SIZE = sizeof(int) + sizeof(double) + sizeof(int);
// const std::size_t MAX_ALIGNMENT = std::max(alignof(double), alignof(int));
const std::size_t MAX_ALIGNMENT = alignof(X); //probably a better approach than above

std::aligned_storage<TOTAL_SIZE, MAX_ALIGNMENT>::type buffer;
X* pX = new(static_cast<void*>(&buffer)) X;

std::cout << "but sizeof(buffer) = " << sizeof(buffer) << std::endl;
pX->a = 10;
pX->b = 12334.5353;
pX->c = 44;

std::cout << pX->a << "t" << pX->b << "t" << pX->c << std::endl;

return 0;



There is no delete, because placement-new handles the allocation, so that it happenes on stack (buffer is a stack variable). Also, something more sophisticated should be passed as template parameters, some compile-time calculations of the desired buffer size and alignment (honestly, that's where I'm not quite sure of myself). ...and maybe you'll have to use types like int16_t, and probably you'd better reorder members of the struct taking into account all the considerations, that have already been proposed about that.



But the primary idea is like that.



AFAIK, different tricks like "Small Object Optimization" are done that way, if you compiler supports the corresponding standard, that trick should save your efforrts. Standard library implementation's sources from GCC are full of similar things, just a lot more well-thought-out.






share|improve this answer



























    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













    draft saved

    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56761591%2fhow-to-organize-members-in-a-struct-to-waste-least-space-on-alignment%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    4 Answers
    4






    active

    oldest

    votes








    4 Answers
    4






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    5














    gcc has the -Wpadded warning that warns when padding is added to a structure:



    https://godbolt.org/z/iwO5Q3:



    <source>:4:12: warning: padding struct to align 'X::b' [-Wpadded]
    4 | double b;
    | ^

    <source>:1:8: warning: padding struct size to alignment boundary [-Wpadded]
    1 | struct X
    | ^


    And you can manually rearrange members so that there is less / no padding. But this is not a cross platform solution, as different types can have different sizes / alignments on different system (Most notably pointers being 4 or 8 bytes on different architectures). The general rule of thumb is go from largest to smallest alignment when declaring members, and if you're still worried, compile your code with -Wpadded once (But I wouldn't keep it on generally, because padding is necessary sometimes).



    As for the reason why the compiler can't do it automatically is because of the standard ([class.mem]/19). It guarantees that, because this is a simple struct with only public members, &x.a < &x.c (for some X x;), so they can't be rearranged.






    share|improve this answer




















    • 1





      I honestly didn't think I'd see something useful come out of this question. Wasn't aware of that gcc option (and now I'm hopign clang has it as well). Thanks for teaching me something. tick.

      – WhozCraig
      9 hours ago















    5














    gcc has the -Wpadded warning that warns when padding is added to a structure:



    https://godbolt.org/z/iwO5Q3:



    <source>:4:12: warning: padding struct to align 'X::b' [-Wpadded]
    4 | double b;
    | ^

    <source>:1:8: warning: padding struct size to alignment boundary [-Wpadded]
    1 | struct X
    | ^


    And you can manually rearrange members so that there is less / no padding. But this is not a cross platform solution, as different types can have different sizes / alignments on different system (Most notably pointers being 4 or 8 bytes on different architectures). The general rule of thumb is go from largest to smallest alignment when declaring members, and if you're still worried, compile your code with -Wpadded once (But I wouldn't keep it on generally, because padding is necessary sometimes).



    As for the reason why the compiler can't do it automatically is because of the standard ([class.mem]/19). It guarantees that, because this is a simple struct with only public members, &x.a < &x.c (for some X x;), so they can't be rearranged.






    share|improve this answer




















    • 1





      I honestly didn't think I'd see something useful come out of this question. Wasn't aware of that gcc option (and now I'm hopign clang has it as well). Thanks for teaching me something. tick.

      – WhozCraig
      9 hours ago













    5












    5








    5







    gcc has the -Wpadded warning that warns when padding is added to a structure:



    https://godbolt.org/z/iwO5Q3:



    <source>:4:12: warning: padding struct to align 'X::b' [-Wpadded]
    4 | double b;
    | ^

    <source>:1:8: warning: padding struct size to alignment boundary [-Wpadded]
    1 | struct X
    | ^


    And you can manually rearrange members so that there is less / no padding. But this is not a cross platform solution, as different types can have different sizes / alignments on different system (Most notably pointers being 4 or 8 bytes on different architectures). The general rule of thumb is go from largest to smallest alignment when declaring members, and if you're still worried, compile your code with -Wpadded once (But I wouldn't keep it on generally, because padding is necessary sometimes).



    As for the reason why the compiler can't do it automatically is because of the standard ([class.mem]/19). It guarantees that, because this is a simple struct with only public members, &x.a < &x.c (for some X x;), so they can't be rearranged.






    share|improve this answer















    gcc has the -Wpadded warning that warns when padding is added to a structure:



    https://godbolt.org/z/iwO5Q3:



    <source>:4:12: warning: padding struct to align 'X::b' [-Wpadded]
    4 | double b;
    | ^

    <source>:1:8: warning: padding struct size to alignment boundary [-Wpadded]
    1 | struct X
    | ^


    And you can manually rearrange members so that there is less / no padding. But this is not a cross platform solution, as different types can have different sizes / alignments on different system (Most notably pointers being 4 or 8 bytes on different architectures). The general rule of thumb is go from largest to smallest alignment when declaring members, and if you're still worried, compile your code with -Wpadded once (But I wouldn't keep it on generally, because padding is necessary sometimes).



    As for the reason why the compiler can't do it automatically is because of the standard ([class.mem]/19). It guarantees that, because this is a simple struct with only public members, &x.a < &x.c (for some X x;), so they can't be rearranged.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 9 hours ago

























    answered 9 hours ago









    ArtyerArtyer

    6,9199 silver badges31 bronze badges




    6,9199 silver badges31 bronze badges







    • 1





      I honestly didn't think I'd see something useful come out of this question. Wasn't aware of that gcc option (and now I'm hopign clang has it as well). Thanks for teaching me something. tick.

      – WhozCraig
      9 hours ago












    • 1





      I honestly didn't think I'd see something useful come out of this question. Wasn't aware of that gcc option (and now I'm hopign clang has it as well). Thanks for teaching me something. tick.

      – WhozCraig
      9 hours ago







    1




    1





    I honestly didn't think I'd see something useful come out of this question. Wasn't aware of that gcc option (and now I'm hopign clang has it as well). Thanks for teaching me something. tick.

    – WhozCraig
    9 hours ago





    I honestly didn't think I'd see something useful come out of this question. Wasn't aware of that gcc option (and now I'm hopign clang has it as well). Thanks for teaching me something. tick.

    – WhozCraig
    9 hours ago













    5














    There really isn't a portable solution in the generic case. Baring minimal requirements the standard imposes, types can be any size the implementation wants to make them.



    To go along with that, The compiler is not allowed to reorder class member to make it more efficient. The standard mandates that the objects must be laid out in their declared order (by access modifier), so that's out as well.



    You can use fixed width types like



    struct foo

    int64_t a;
    int16_t b;
    int8_t c;
    int8_t d;
    ;


    and this will be the same on all platforms, provided they supply those types, but it only works with integer types. There are no fixed width floating point types and many standard objects/containers can be different sizes on different platforms.






    share|improve this answer

























    • Adding salt to the wound, floating point types are frequently hyper sensitive to bus-alignment positions, thereby enhancing the no-silver-bullet mantra. Regardless, this is very useful when loading up structs with anything other than floating point and potentially pointers. I use it frequently.

      – WhozCraig
      9 hours ago











    • Why isn’t member rearrangement allowed? Could you clarify?

      – Yan B.
      9 hours ago






    • 2





      If you take the cross-platform portability to the limit, note that these "exact width" types are optional. Every platform must have int_least16_t and int_fast16_t, but (for example if CHAR_BIT != 8), int16_t need not exist on a given platform.

      – DevSolar
      9 hours ago











    • @DevSolar While they are optional, the code will fail to compile if they are not present so at least you wont get binary that blows up on you.

      – NathanOliver
      9 hours ago






    • 1





      @YanB. It is mandated by the standard. see: eel.is/c++draft/class.mem#19

      – NathanOliver
      9 hours ago















    5














    There really isn't a portable solution in the generic case. Baring minimal requirements the standard imposes, types can be any size the implementation wants to make them.



    To go along with that, The compiler is not allowed to reorder class member to make it more efficient. The standard mandates that the objects must be laid out in their declared order (by access modifier), so that's out as well.



    You can use fixed width types like



    struct foo

    int64_t a;
    int16_t b;
    int8_t c;
    int8_t d;
    ;


    and this will be the same on all platforms, provided they supply those types, but it only works with integer types. There are no fixed width floating point types and many standard objects/containers can be different sizes on different platforms.






    share|improve this answer

























    • Adding salt to the wound, floating point types are frequently hyper sensitive to bus-alignment positions, thereby enhancing the no-silver-bullet mantra. Regardless, this is very useful when loading up structs with anything other than floating point and potentially pointers. I use it frequently.

      – WhozCraig
      9 hours ago











    • Why isn’t member rearrangement allowed? Could you clarify?

      – Yan B.
      9 hours ago






    • 2





      If you take the cross-platform portability to the limit, note that these "exact width" types are optional. Every platform must have int_least16_t and int_fast16_t, but (for example if CHAR_BIT != 8), int16_t need not exist on a given platform.

      – DevSolar
      9 hours ago











    • @DevSolar While they are optional, the code will fail to compile if they are not present so at least you wont get binary that blows up on you.

      – NathanOliver
      9 hours ago






    • 1





      @YanB. It is mandated by the standard. see: eel.is/c++draft/class.mem#19

      – NathanOliver
      9 hours ago













    5












    5








    5







    There really isn't a portable solution in the generic case. Baring minimal requirements the standard imposes, types can be any size the implementation wants to make them.



    To go along with that, The compiler is not allowed to reorder class member to make it more efficient. The standard mandates that the objects must be laid out in their declared order (by access modifier), so that's out as well.



    You can use fixed width types like



    struct foo

    int64_t a;
    int16_t b;
    int8_t c;
    int8_t d;
    ;


    and this will be the same on all platforms, provided they supply those types, but it only works with integer types. There are no fixed width floating point types and many standard objects/containers can be different sizes on different platforms.






    share|improve this answer















    There really isn't a portable solution in the generic case. Baring minimal requirements the standard imposes, types can be any size the implementation wants to make them.



    To go along with that, The compiler is not allowed to reorder class member to make it more efficient. The standard mandates that the objects must be laid out in their declared order (by access modifier), so that's out as well.



    You can use fixed width types like



    struct foo

    int64_t a;
    int16_t b;
    int8_t c;
    int8_t d;
    ;


    and this will be the same on all platforms, provided they supply those types, but it only works with integer types. There are no fixed width floating point types and many standard objects/containers can be different sizes on different platforms.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 9 hours ago

























    answered 9 hours ago









    NathanOliverNathanOliver

    106k19 gold badges159 silver badges235 bronze badges




    106k19 gold badges159 silver badges235 bronze badges












    • Adding salt to the wound, floating point types are frequently hyper sensitive to bus-alignment positions, thereby enhancing the no-silver-bullet mantra. Regardless, this is very useful when loading up structs with anything other than floating point and potentially pointers. I use it frequently.

      – WhozCraig
      9 hours ago











    • Why isn’t member rearrangement allowed? Could you clarify?

      – Yan B.
      9 hours ago






    • 2





      If you take the cross-platform portability to the limit, note that these "exact width" types are optional. Every platform must have int_least16_t and int_fast16_t, but (for example if CHAR_BIT != 8), int16_t need not exist on a given platform.

      – DevSolar
      9 hours ago











    • @DevSolar While they are optional, the code will fail to compile if they are not present so at least you wont get binary that blows up on you.

      – NathanOliver
      9 hours ago






    • 1





      @YanB. It is mandated by the standard. see: eel.is/c++draft/class.mem#19

      – NathanOliver
      9 hours ago

















    • Adding salt to the wound, floating point types are frequently hyper sensitive to bus-alignment positions, thereby enhancing the no-silver-bullet mantra. Regardless, this is very useful when loading up structs with anything other than floating point and potentially pointers. I use it frequently.

      – WhozCraig
      9 hours ago











    • Why isn’t member rearrangement allowed? Could you clarify?

      – Yan B.
      9 hours ago






    • 2





      If you take the cross-platform portability to the limit, note that these "exact width" types are optional. Every platform must have int_least16_t and int_fast16_t, but (for example if CHAR_BIT != 8), int16_t need not exist on a given platform.

      – DevSolar
      9 hours ago











    • @DevSolar While they are optional, the code will fail to compile if they are not present so at least you wont get binary that blows up on you.

      – NathanOliver
      9 hours ago






    • 1





      @YanB. It is mandated by the standard. see: eel.is/c++draft/class.mem#19

      – NathanOliver
      9 hours ago
















    Adding salt to the wound, floating point types are frequently hyper sensitive to bus-alignment positions, thereby enhancing the no-silver-bullet mantra. Regardless, this is very useful when loading up structs with anything other than floating point and potentially pointers. I use it frequently.

    – WhozCraig
    9 hours ago





    Adding salt to the wound, floating point types are frequently hyper sensitive to bus-alignment positions, thereby enhancing the no-silver-bullet mantra. Regardless, this is very useful when loading up structs with anything other than floating point and potentially pointers. I use it frequently.

    – WhozCraig
    9 hours ago













    Why isn’t member rearrangement allowed? Could you clarify?

    – Yan B.
    9 hours ago





    Why isn’t member rearrangement allowed? Could you clarify?

    – Yan B.
    9 hours ago




    2




    2





    If you take the cross-platform portability to the limit, note that these "exact width" types are optional. Every platform must have int_least16_t and int_fast16_t, but (for example if CHAR_BIT != 8), int16_t need not exist on a given platform.

    – DevSolar
    9 hours ago





    If you take the cross-platform portability to the limit, note that these "exact width" types are optional. Every platform must have int_least16_t and int_fast16_t, but (for example if CHAR_BIT != 8), int16_t need not exist on a given platform.

    – DevSolar
    9 hours ago













    @DevSolar While they are optional, the code will fail to compile if they are not present so at least you wont get binary that blows up on you.

    – NathanOliver
    9 hours ago





    @DevSolar While they are optional, the code will fail to compile if they are not present so at least you wont get binary that blows up on you.

    – NathanOliver
    9 hours ago




    1




    1





    @YanB. It is mandated by the standard. see: eel.is/c++draft/class.mem#19

    – NathanOliver
    9 hours ago





    @YanB. It is mandated by the standard. see: eel.is/c++draft/class.mem#19

    – NathanOliver
    9 hours ago











    0














    You can use #pragma pack(1), but the very reason of this is that the compiler optimizes. Accessing a variable through the full register is faster than accessing it to the least bit.



    Specific packing is only useful for serialization and intercompiler compatibility, etc.



    As NathanOliver correctly added, this might even fail on some platforms.






    share|improve this answer




















    • 3





      May want to note this carries potential performance issues or may cause the code to not work on some platforms: stackoverflow.com/questions/7793511/…

      – NathanOliver
      9 hours ago






    • 1





      To my knowledge, using #pragma pack causes potential performance issues and as such is not the desired solution.

      – Yan B.
      9 hours ago















    0














    You can use #pragma pack(1), but the very reason of this is that the compiler optimizes. Accessing a variable through the full register is faster than accessing it to the least bit.



    Specific packing is only useful for serialization and intercompiler compatibility, etc.



    As NathanOliver correctly added, this might even fail on some platforms.






    share|improve this answer




















    • 3





      May want to note this carries potential performance issues or may cause the code to not work on some platforms: stackoverflow.com/questions/7793511/…

      – NathanOliver
      9 hours ago






    • 1





      To my knowledge, using #pragma pack causes potential performance issues and as such is not the desired solution.

      – Yan B.
      9 hours ago













    0












    0








    0







    You can use #pragma pack(1), but the very reason of this is that the compiler optimizes. Accessing a variable through the full register is faster than accessing it to the least bit.



    Specific packing is only useful for serialization and intercompiler compatibility, etc.



    As NathanOliver correctly added, this might even fail on some platforms.






    share|improve this answer















    You can use #pragma pack(1), but the very reason of this is that the compiler optimizes. Accessing a variable through the full register is faster than accessing it to the least bit.



    Specific packing is only useful for serialization and intercompiler compatibility, etc.



    As NathanOliver correctly added, this might even fail on some platforms.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 9 hours ago

























    answered 9 hours ago









    Michael ChourdakisMichael Chourdakis

    3,9761 gold badge20 silver badges44 bronze badges




    3,9761 gold badge20 silver badges44 bronze badges







    • 3





      May want to note this carries potential performance issues or may cause the code to not work on some platforms: stackoverflow.com/questions/7793511/…

      – NathanOliver
      9 hours ago






    • 1





      To my knowledge, using #pragma pack causes potential performance issues and as such is not the desired solution.

      – Yan B.
      9 hours ago












    • 3





      May want to note this carries potential performance issues or may cause the code to not work on some platforms: stackoverflow.com/questions/7793511/…

      – NathanOliver
      9 hours ago






    • 1





      To my knowledge, using #pragma pack causes potential performance issues and as such is not the desired solution.

      – Yan B.
      9 hours ago







    3




    3





    May want to note this carries potential performance issues or may cause the code to not work on some platforms: stackoverflow.com/questions/7793511/…

    – NathanOliver
    9 hours ago





    May want to note this carries potential performance issues or may cause the code to not work on some platforms: stackoverflow.com/questions/7793511/…

    – NathanOliver
    9 hours ago




    1




    1





    To my knowledge, using #pragma pack causes potential performance issues and as such is not the desired solution.

    – Yan B.
    9 hours ago





    To my knowledge, using #pragma pack causes potential performance issues and as such is not the desired solution.

    – Yan B.
    9 hours ago











    0














    Well, maybe I'm cooking the concept wrong, but you can use std::aligned_storage to allocate your data. Applied to the struct, considered above, it could be something like that:



    #include <type_traits>
    #include <iostream>
    #include <algorithm>

    struct X

    int a;
    double b;
    int c;
    ;


    int main()

    const std::size_t TOTAL_SIZE = sizeof(int) + sizeof(double) + sizeof(int);
    // const std::size_t MAX_ALIGNMENT = std::max(alignof(double), alignof(int));
    const std::size_t MAX_ALIGNMENT = alignof(X); //probably a better approach than above

    std::aligned_storage<TOTAL_SIZE, MAX_ALIGNMENT>::type buffer;
    X* pX = new(static_cast<void*>(&buffer)) X;

    std::cout << "but sizeof(buffer) = " << sizeof(buffer) << std::endl;
    pX->a = 10;
    pX->b = 12334.5353;
    pX->c = 44;

    std::cout << pX->a << "t" << pX->b << "t" << pX->c << std::endl;

    return 0;



    There is no delete, because placement-new handles the allocation, so that it happenes on stack (buffer is a stack variable). Also, something more sophisticated should be passed as template parameters, some compile-time calculations of the desired buffer size and alignment (honestly, that's where I'm not quite sure of myself). ...and maybe you'll have to use types like int16_t, and probably you'd better reorder members of the struct taking into account all the considerations, that have already been proposed about that.



    But the primary idea is like that.



    AFAIK, different tricks like "Small Object Optimization" are done that way, if you compiler supports the corresponding standard, that trick should save your efforrts. Standard library implementation's sources from GCC are full of similar things, just a lot more well-thought-out.






    share|improve this answer





























      0














      Well, maybe I'm cooking the concept wrong, but you can use std::aligned_storage to allocate your data. Applied to the struct, considered above, it could be something like that:



      #include <type_traits>
      #include <iostream>
      #include <algorithm>

      struct X

      int a;
      double b;
      int c;
      ;


      int main()

      const std::size_t TOTAL_SIZE = sizeof(int) + sizeof(double) + sizeof(int);
      // const std::size_t MAX_ALIGNMENT = std::max(alignof(double), alignof(int));
      const std::size_t MAX_ALIGNMENT = alignof(X); //probably a better approach than above

      std::aligned_storage<TOTAL_SIZE, MAX_ALIGNMENT>::type buffer;
      X* pX = new(static_cast<void*>(&buffer)) X;

      std::cout << "but sizeof(buffer) = " << sizeof(buffer) << std::endl;
      pX->a = 10;
      pX->b = 12334.5353;
      pX->c = 44;

      std::cout << pX->a << "t" << pX->b << "t" << pX->c << std::endl;

      return 0;



      There is no delete, because placement-new handles the allocation, so that it happenes on stack (buffer is a stack variable). Also, something more sophisticated should be passed as template parameters, some compile-time calculations of the desired buffer size and alignment (honestly, that's where I'm not quite sure of myself). ...and maybe you'll have to use types like int16_t, and probably you'd better reorder members of the struct taking into account all the considerations, that have already been proposed about that.



      But the primary idea is like that.



      AFAIK, different tricks like "Small Object Optimization" are done that way, if you compiler supports the corresponding standard, that trick should save your efforrts. Standard library implementation's sources from GCC are full of similar things, just a lot more well-thought-out.






      share|improve this answer



























        0












        0








        0







        Well, maybe I'm cooking the concept wrong, but you can use std::aligned_storage to allocate your data. Applied to the struct, considered above, it could be something like that:



        #include <type_traits>
        #include <iostream>
        #include <algorithm>

        struct X

        int a;
        double b;
        int c;
        ;


        int main()

        const std::size_t TOTAL_SIZE = sizeof(int) + sizeof(double) + sizeof(int);
        // const std::size_t MAX_ALIGNMENT = std::max(alignof(double), alignof(int));
        const std::size_t MAX_ALIGNMENT = alignof(X); //probably a better approach than above

        std::aligned_storage<TOTAL_SIZE, MAX_ALIGNMENT>::type buffer;
        X* pX = new(static_cast<void*>(&buffer)) X;

        std::cout << "but sizeof(buffer) = " << sizeof(buffer) << std::endl;
        pX->a = 10;
        pX->b = 12334.5353;
        pX->c = 44;

        std::cout << pX->a << "t" << pX->b << "t" << pX->c << std::endl;

        return 0;



        There is no delete, because placement-new handles the allocation, so that it happenes on stack (buffer is a stack variable). Also, something more sophisticated should be passed as template parameters, some compile-time calculations of the desired buffer size and alignment (honestly, that's where I'm not quite sure of myself). ...and maybe you'll have to use types like int16_t, and probably you'd better reorder members of the struct taking into account all the considerations, that have already been proposed about that.



        But the primary idea is like that.



        AFAIK, different tricks like "Small Object Optimization" are done that way, if you compiler supports the corresponding standard, that trick should save your efforrts. Standard library implementation's sources from GCC are full of similar things, just a lot more well-thought-out.






        share|improve this answer















        Well, maybe I'm cooking the concept wrong, but you can use std::aligned_storage to allocate your data. Applied to the struct, considered above, it could be something like that:



        #include <type_traits>
        #include <iostream>
        #include <algorithm>

        struct X

        int a;
        double b;
        int c;
        ;


        int main()

        const std::size_t TOTAL_SIZE = sizeof(int) + sizeof(double) + sizeof(int);
        // const std::size_t MAX_ALIGNMENT = std::max(alignof(double), alignof(int));
        const std::size_t MAX_ALIGNMENT = alignof(X); //probably a better approach than above

        std::aligned_storage<TOTAL_SIZE, MAX_ALIGNMENT>::type buffer;
        X* pX = new(static_cast<void*>(&buffer)) X;

        std::cout << "but sizeof(buffer) = " << sizeof(buffer) << std::endl;
        pX->a = 10;
        pX->b = 12334.5353;
        pX->c = 44;

        std::cout << pX->a << "t" << pX->b << "t" << pX->c << std::endl;

        return 0;



        There is no delete, because placement-new handles the allocation, so that it happenes on stack (buffer is a stack variable). Also, something more sophisticated should be passed as template parameters, some compile-time calculations of the desired buffer size and alignment (honestly, that's where I'm not quite sure of myself). ...and maybe you'll have to use types like int16_t, and probably you'd better reorder members of the struct taking into account all the considerations, that have already been proposed about that.



        But the primary idea is like that.



        AFAIK, different tricks like "Small Object Optimization" are done that way, if you compiler supports the corresponding standard, that trick should save your efforrts. Standard library implementation's sources from GCC are full of similar things, just a lot more well-thought-out.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 7 hours ago

























        answered 8 hours ago









        MasterAlerMasterAler

        68711 silver badges20 bronze badges




        68711 silver badges20 bronze badges



























            draft saved

            draft discarded
















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid


            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.

            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56761591%2fhow-to-organize-members-in-a-struct-to-waste-least-space-on-alignment%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            ParseJSON using SSJSUsing AMPscript with SSJS ActivitiesHow to resubscribe a user in Marketing cloud using SSJS?Pulling Subscriber Status from Lists using SSJSRetrieving Emails using SSJSProblem in updating DE using SSJSUsing SSJS to send single email in Marketing CloudError adding EmailSendDefinition using SSJS

            Кампала Садржај Географија Географија Историја Становништво Привреда Партнерски градови Референце Спољашње везе Мени за навигацију0°11′ СГШ; 32°20′ ИГД / 0.18° СГШ; 32.34° ИГД / 0.18; 32.340°11′ СГШ; 32°20′ ИГД / 0.18° СГШ; 32.34° ИГД / 0.18; 32.34МедијиПодациЗванични веб-сајту

            19. јануар Садржај Догађаји Рођења Смрти Празници и дани сећања Види још Референце Мени за навигацијуу