All pointers are the same size. A char pointer is the same size as an int pointer is the same size as a someCrazyObject pointer. They are usually the same size as an int; commonly 4 or 8 bytes depending on whether you've a 32 or 64 bit system.
You need only five bytes to store the contents of any Foo object. However, an array of 100 such objects will occupy 800 bytes, not 500. The compiler must skip 3 bytes before placing the next element of the array of Foo in RAM, because of the way computer hardware works.
sizeof(Foo) will also return 8, not five, and that is because operator sizeof(T) does not actually return the size of the object of type T. It returns the size of an array element, for some imaginary array of objects of size T.
It's not because of the way computer hardware works. It's a technique used to try and increase performance, a multiplication of 8, which is a power of 2, is faster (a simple bit shift) than a multiplication of 5.
> sizeof(T) does not actually return the size of the object of type T
The IS distinguishes between the 'object representation' and the 'value representation' of an object.
The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T). The value representation of an object is the set of bits that hold the value of type T. For trivially copyable types, the value representation is a set of bits in the object representation that determines a value, which is one discrete element of an implementation-defined set ofvalues.
sizeof(T) gives the number of bytes of the 'object representation' of an object of type T would take - that size is the same whether the object is an element of an array or not.
@xerzi
Actually, it is a combination of the way computer hardware works and performance.
On some processors, it is simply impossible to read a 4-byte value such as "float a" on any address which is not aligned to a multiple of 4-bytes. Attempting to do so may either result in a mis-aligned address exception, or the address may be forcibly aligned to a different address (instead of reading the 4-byte float at 0x12345555, the processor will silently read the 4-byte float at 0x12345554). Even if a processor does support a mis-aligned read, that read may (depending upon both the processor architecture and the alignment) be slower as it may be broken up into multiple aligned reads.
Also, multiplying by 8 may or may not be faster than shifting a value by 3 bits. It all depends upon the processor architecture, but most high-performance processors will do both multiplication and shift instructions in a single clock cycle. Some embedded processors can shift more quickly than they can multiply, while other embedded processors require 3 1-bit shift instructions vs. a 2 instruction multiply (immediate load + multiply).
@JLBorges
That standard quote is incomplete as it refers to the definition of sizeof, which you did not quote
ยง5.3.2[expr.sizeof]/2
When applied to a class, the result is the number of bytes in an object of that class including any padding required for placing objects of that type in an array
But yes, the actual term for that element of the imaginary array of T is "object representation of T"
@mpauna
Why would a bitshift ever be slower than a multiplication? As far as I know [which isn't that "far", mind you], there is no way to do an "instant" multiplication. A bitshift, however, should always be a single instruction, regardless of the number of bits shifted. I don't see why a "3shift" would ever be processed as "3x 1shift".
In that example there is only a single type which is one char, a char can be aligned anywhere in memory as apposed to a float. You'd probably never see a float purposely put at an address that isn't a multiple of 4.
> That standard quote is incomplete as it refers to the definition of sizeof, which you did not quote
Yes. I should have quoted that.
The point I was trying to make is that 'the number of bytes in an object of that class including any padding required for placing objects of that type in an array' is part of the amount of memory an object uses up, even when it is not placed into an array. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
struct A
{
int i ;
char c ;
};
struct B
{
A a ;
char c ;
};
int main()
{
std::cout << sizeof(A) << ' ' << sizeof(B) << '\n' ; // 8 12 on my implementation
}
xerzi: right, float has an alignment requirement of 4, which affects the alignment requirement of the type that holds it as a data member. This has nothing to do with multiplication by 8 being possibly faster than multiplication by 5.
It is a compiler option, if you wanted to you could set that option to 1, by default it is set to 8. You can only set these options to multiples of 2 for the reason of efficiency. In the end it boils down to the compiler, not hardware restrictions.
The point I was trying to make is that 'the number of bytes in an object of that class including any padding required for placing objects of that type in an array' is part of the amount of memory an object uses up, even when it is not placed into an array.
True that an object can't "use up" less memory than that, if stored in RAM, but in some non-array situations, object representations may overlap: e.g. base subobject's padding is used to store derived's data members.
But this is all getting too far off the main topic, which is that the size of an array N of T is exactly N*sizeof(T), by definition.
This is drifting a bit off of the original topic ...
@gaminic
Why would a bitshift ever be slower than a multiplication?
It all depends upon the processor. There are some processors which have bit shift instructions and some which do not. Some processors have instructions which only shift 1 bit at a time, while other processors have instructions which can shift by constant # of bits and/or by the # of bits specified by a register.
While one processor may support asl r1,#3
another processor might require
1 2 3
asl r1
asl r1
asl r1
and another processor might require
1 2 3
add r1,r1
add r1,r1
add r1,r1
some processors might even use something like
1 2
rol r4,#29
mask r4,0xFFFFFFF8
Why wouldn't a processor support a multi-bit shift instruction? Usually it is because there are not enough instruction bits to fit all of the desired instructions.