Compiler outputting wrong size

Pages: 123
@JLBorges

BUT WHAT DO YOU MEAN BY STRINGENT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Also why is long doubles alignment 4? o.O. Shouldnt it be 12...?


Second Question:

Ill make a example tomorrow, I need to sleep now, Good night!


@Anmol444

I wouldn't worry about protected or private class inheritance for now - just stick with public. There are some uses for private (not many I gather) & even Scott Meyers hasn't figured out why one would need protected.

With the stringent - read more carefully what JLBorges said.

Framework has already explained why there can't be alignment 12.

Hope all goes well.
> BUT WHAT DO YOU MEAN BY STRINGENT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

rigorously binding or exacting; strict; severe - http://dictionary.com
stringent often means simply 'strict, strictly regulated' and also 'tight or constricted' and emphasizes the narrowness of what is permitted, while strict emphasizes the sternness with which something is enforced - http://thesaurus.com/


An object of type long double can be placed in memory starting at an address that is a multiple of four; but an object of type double can only be placed starting at an address which is a multiple of eight (in the above implementation).

The alignment requirement of double is more exacting (more restricted) than that of long double; a double can't be placed at every address that a long double can be placed; or in other words, the alignment requirement of double is 'more stringent' than that of long double.


> Also why is long doubles alignment 4? o.O. Shouldnt it be 12...?

Alignment depends on the implementation. There is no guarantee that the alignment of long double is 4 everywhere; it may well be 12 on a different implementation (for instance one where a byte consists of 8 bits, sizeof(long double) is 12 and the architecture has 96-bit registers along with a 96-bit data bus).
Last edited on
@JLBorges

On my compiler VC++, the size is 8 bytes and its alignment is also 8.

Also what does double have to do with long double? Aren't they both completely different types???

@TheIdeasMan
Framework didnt explain that?

But thanks, also I was just asking so that I know for the future. Can you still answer it though? Please, I really like making sure I know and understand it.
> On my compiler VC++, the size is 8 bytes and its alignment is also 8.

Repeat: size, alignment and value-representation of double and long double are implementation-defined.

Subject to the proviso that:
a. the precision that long double provides is not less than the precision that a double provides.
(It may be greater.)

b. the set of values that the type long double can hold is a (not necessarily proper) superset of the set of values that the type double can hold.


> Also what does double have to do with long double?

Both are floating point types; due to the provisions a. and b. above,
the conversion from a long double to a double is a narrowing conversion.


> Aren't they both completely different types???

They are two different types. However, they may (or may not) have the same object representation. Even if they happen to have the same object representation (the same value representation, the same size and the same alignment) on a particular implementation, double and long double are two distinct fundamental types.


> I really like making sure I know and understand it.

The basic idea is extremely simple; you are unnecessarily complicating it by trying to factor in completely irrelevant issues like size.

Object types have alignment requirements which place restrictions on the addresses at which an object of that type may be allocated. An alignment is an implementation-defined integer value representing the number of bytes between successive addresses at which a given object can be allocated. An object type imposes an alignment requirement on every object of that type
...
Alignments have an order from weaker to stronger or stricter alignments. Stricter alignments have larger alignment values. An address that satisfies an alignment requirement also satisfies any weaker valid alignment requirement.
...
Comparing alignments is meaningful and provides the obvious results:
— Two alignments are equal when their numeric values are equal.
— Two alignments are different when their numeric values are not equal.
— When an alignment is larger than another it represents a stricter alignment.


Incidentally, the term 'more stringent alignment requirement' that I used earlier has the same meaning as the term 'stronger or stricter alignment' used by the IS.


Oh I got what you mean now, by more stringent you mean more exact. So if a double has 4 byte alignment but the size of double is 8 it is less stringent then a int with 4 bytes and 4 byte alignment.

Or you just mean the larger alignment right?
Last edited on
There is just one small thing I need some clarification on.

If it is aligning by 8's then does that mean that the 3 doubles take up 24 bytes which is why at first it is 24 bytes. Although the pointer is 4 bytes why is it taking up 8 bytes. So the compiler counts the bytes that are not used up?

And the bytes that are not used up cannot be used by another object because the other object would be placed on the next address right?

I am really confused on this. I understand the concept of memory alignment.

Can you draw it on MS paint or something to show me how it would all look?

Thanks!
Last edited on
TheIdeasMan wrote:
even Scott Meyers hasn't figured out why one would need protected.
Strange, I've found plenty of uses. For example, derived classes passing themselves to a function that takes as an argument one of their base class' protected bases.
@L B

Yea that's the use I would use it for as well. Although you can just put the function in the base class public section its easier like that.

Anmol444 wrote:
Although you can just put the function in the base class public section its easier like that.
Tell me how you would do that with this code:
1
2
3
4
5
6
7
8
9
10
11
12
13
void f(BaseB const &bb);

struct DerivedA : BaseA, protected BaseB, private BaseC
{
    virtual void doSomething(){}
};
struct DerivedB : DerivedA
{
    virtual void doSomething()
    {
        f(*this);
    }
};
Last edited on
Well you cant really, cause you dont have access to the code of BaseA and BaseB and BaseC.

Also I phrased it wrong, by easier I meant easier your way lol
Last edited on
"My way" is the situation where you must use protected inheritance that you said you had an alternative to :p
Last edited on
My alternative sucks, You RULE!

Also sorry if alot of my questions are stupid, I aint a very smart person...

But thanks for helping guys, I hope you can answer my very last question soon JLBorges, thanks!!!!!
> If it is aligning by 8's then does that mean that the 3 doubles take up 24 bytes

3 doubles will take up 3 * sizeof(double) bytes.
Each of those three doubles will be placed in memory aligned to std::alignment_of<double>::value.

If on a particular implementation, sizeof(double) == 24,
then the size of 3 doubles ie. sizeof( double[3] ) == 72.

If on that particular implementation, std::alignment_of<double>::value == 2
each of those three objects of type double will start at an address which is a multiple of 2.

And if on that particular implementation, sizeof<double*> == 4,
an object of type pointer to double will occupy 4 bytes of memory
And if std::alignment_of<double*>::value == 8
it will be placed an address which is a multiple of 8.


In general, n objects of type T will take up n * sizeof(T) bytes.
Each of those n objects will be placed in memory aligned to std::alignment_of<T>::value.
So they are be being placed at 8, 16, and 24?
Can you please draw it out for me. The alignments that was in the code I showed?
Actually I will try to draw, just tell me if I got it right!
> Can you please draw it out for me. The alignments that was in the code I showed?

The layout (object representation) of a type is implementation defined. That means it could be different on different implementations.


On any implementation:

For any type T, use sizeof(T) to portably get the size.

For any type T, use std::alignment_of<T>::value to portably get the alignment.

For any pod type T, use the offsetof() macro (defined in cstddef) to portably get the offset of non-static member variables.

For this program:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <type_traits>
#include <cstddef>

#define SHOW_SIZE_ALIGNMENT(T) ( std::cout << "type: " << #T << "  size: " \
          << sizeof(T) << "  alignment: " << std::alignment_of<T>::value << '\n' )

// *** warning *** use only on pods
#define SHOW_OFFSET( type, member ) ( std::cout << "type: " << #type << "  member: " \
          << #member << "  offset: " << offsetof(type,member) << '\n' )

// *** warning *** use only on pods
// *** warning *** assumes that size of the object is < 128 MB
// *** warning *** assumes that pointer  arithmetic is well defined for
                // addresses in the range (134217728-sizeof(derived)) to 134217728
#define offsetofbase( derived, base ) ( reinterpret_cast<std::ptrdiff_t>( \
                    static_cast<base*>( reinterpret_cast<derived*>(134217728) ) ) \
                       - 134217728 )

#define SHOW_OFFSET_OF_BASE( derived, base ) ( std::cout << "derived class: " << #derived \
          << "  base class: "  << #base << "  offset: " << offsetofbase(derived,base) << '\n' )

struct box
{
    double length ;
    double width ;
    double height ;
};

struct candy_box : box { char* contents ; };

int main()
{
    SHOW_SIZE_ALIGNMENT(double) ;
    SHOW_SIZE_ALIGNMENT(box) ;

    SHOW_OFFSET( box, length ) ;
    SHOW_OFFSET( box, width ) ;
    SHOW_OFFSET( box, height ) ;


    SHOW_SIZE_ALIGNMENT(char*) ;
    SHOW_SIZE_ALIGNMENT(candy_box) ;

    SHOW_OFFSET_OF_BASE( candy_box, box ) ;
    SHOW_OFFSET( candy_box, contents ) ;
}


On my implementation, I get:
type: double  size: 8  alignment: 8
type: box  size: 24  alignment: 8
type: box  member: length  offset: 0
type: box  member: width  offset: 8
type: box  member: height  offset: 16
type: char*  size: 4  alignment: 4
type: candy_box  size: 32  alignment: 8
derived class: candy_box  base class: box  offset: 0
type: candy_box  member: contents  offset: 24


And so, on that specific implementation, the object layouts look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// box
          
          |                |  24
          |                | 
          |     height     |                    higher address
          |                |                           ^
          |                |                           | 
          |----------------| 16                        |  
          |                |                           |
          |                |                           | 
          |     width      | 
          |                |                    lower address
          |                | 
          |----------------| 8
          |                | 
          |                | 
          |     length     | 
          |                | 
          |                | 
box* ---->|----------------| 0


// candy_box
                |----------------| 32
                |                |  
                |                | 
                |    padding     | 
                |                | 
                |                | 
                |----------------| 28
                |                | 
                |    contents    | 
                |                | 
                |                | 
                |----------------| 24
                |                | 
                |                | 
                |                | 
                |                | 
                |                | 
                |                | 
                |                | 
                |    anonymous   | 
                |    base class  | 
                |    object of   | 
                |    type box    | 
                |                | 
                |                | 
                |                | 
                |                | 
                |                | 
candy_box* ---->|----------------| 0


Note: candy_box has 4 bytes padding added at the end to make the size an integral multiple of its alignment.
(In an array of candy_box objects every candy_box object must be aligned on an 8 byte boundary)
Also why can I add a variable to candybox without its value increasing? Can more then 1 variable be in the 8 byte box?
Pages: 123