Memory size

Pages: 12
This might sound stupid but if a float uses 4Bytes does on array of 100 Floats use 400 Bytes?
yup!!
You can use next link to find answer on your question: http://codepad.org/wtxdJ8yl
So what about an array of character pointers? (assuming it's on a 32 bit system!!)

If a character is 2B, a pointer pointing to it will be 4B right (as pointers are 4B?)?

Therefore an array of 100 character pointers will be 400B! Am i right??

Thanks
Yes, except that a char is (usually) 1byte. Any (regular) pointer is 4bytes.
Wait! So is a character pointer 1byte or 4bytes?
So is a character pointer 1byte or 4bytes?


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.

In C++, a char is by definition one byte.
Last edited on
It isn't a stupid question, consider this type:

1
2
3
4
struct Foo {
    float f;
    char c;
};


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.
closed account (o1vk4iN6)
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.

1
2
3
4
5
6
7
8
9
10
11
12
// MSVC compiler

#pragma pack(push)
#pragma pack(1)
	struct Foo {
		float a;
		char c;
	};
#pragma pack(pop)

cout << sizeof(Foo); // output is 5
Last edited on
> 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"
Last edited on
@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".
xerzi wrote:
It's not because of the way computer hardware works. It's a technique used to try and increase performance,

No. Simple counter-example is

1
2
3
4
5
6
7
8
9
10
#include <iostream>
struct Foo {
     char c[5];
};
int main()
{
        std::cout << sizeof(Foo) << '\n';
        Foo a[100];
        std::cout << sizeof a << '\n';
}
5
500

closed account (o1vk4iN6)
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.

It'd be no different than doing:

 
char a[500];


> 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.
Last edited on
closed account (o1vk4iN6)
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.
JLBorges wrote:
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.

Pages: 12