I am working with c++, I saw this question in my book.
how many bytes will be occupied by this declaration?
float** p[5][10][2];
and there is no extra information about the memory of that machine?
is it possible to tell an explicit answer for this?
It's implementation dependent. So you'd find out with:
float** p[5][10][2];
std::cout << "sizeof(p) == " << sizeof(p) << '\n';
Just to clarify. Here, you are declaring a 3D matrix which elements are pointers to something/float. Since you have 5x10x2 = 100 pointers, and pointers occupy 4b or 8b, the answer can be 400b or 800b.
Don't mess this with 100 * sizeof(float), because elements of matrix arent floats.
It depends on the platforms.
In x86 platform, it occupies 5*10*2*4 bytes, because any pointer occupies 4 bytes in the platform.
So, it occupies 5*10*2*8 bytes in x64 platform.
Related
I am learning C++, and read that when an array is passed into a function it decays into a pointer. I wanted to play around with this and wrote the following function:
void size_print(int a[]){
cout << sizeof(a)/sizeof(a[0]) << endl;
cout << "a ->: " << sizeof(a) << endl;
cout << "a[0] ->" << sizeof(a[0]) << endl;
}
I tried inputting an array with three elements, let's say
int test_array[3] = {1, 2, 3};
With this input, I was expecting this function to print 1, as I thought a would be an integer pointer (4 bytes) and a[0] would also be 4 bytes. However, to my surprise the result is 2 and sizeof(a) = 8.
I cannot figure out why a takes up 8 bytes, but a[0] takes up 4. Shouldn't they be the same?
Shouldn't they be the same?
No. a is (meant to be) an array (but because it's a function argument, has been adjusted to a pointer to the 1st element), and as such, has the size of a pointer. Your machine seems to have 64 bit addresses, and thus, each address (and hence, each pointer) is 64 bits (8 bytes) long.
a[0], on the other hand, is of the type that an element of that array has (an int), and that type has 32 bits (4 bytes) on your machine.
A pointer is just an address of memory where the start of the variable is located. That address is 8 bytes.
a[0] is a variable in the first place of the array. It technically could be anything of whatever size. When you take a pointer to it, the pointer just contains an address of memory (integer) without knowing or caring what this address contains. (This is just to illustrate the concept, in the example in the question, a[] is an integer array but the same logic works with anything).
Note, the size of the pointer is actually different on different architectures. This is where the 32-bit, 64-bit, etc. comes in. It can also depend on the compiler but this is beyond the question.
The size of the pointer depends on the system and implementation. Your uses 64 bits (8 bytes).
a[0] is an integer and the standard only gives an indication of the minimum max value it has to store. It can be anything from 2 bytes up. Most modern implementations use 32 bits (4 bytes) integers.
sizeof(a)/sizeof(a[0]) will not work on the function parameters. Arrays are passed by the reference and this division will only give you information how many times size of the pointer is larger than the size of an integer, but not the size of the object referenced by the pointer.
I wrote a simple program in order to understand the functioning of the function of the standard c++ library sizeof().
It follows:
const char* array[] = {
"1234",
"5678"
};
std::cout << sizeof(array) << std::endl;//16
std::cout << sizeof (array[0]) << std::endl;//8
std::cout << printf("%lu\n",sizeof (char) );//1
std::cout << printf("%lu\n",sizeof (int) );//24
std::cout << printf("%lu\n",sizeof (float) );//24
std::cout << printf("%lu",sizeof (double) );//281
It is possible to see by the output reported the characters has dimension 1 byte in my OS, as
expectable. But I do not understand why the dimension of '''array[0]''' is 8, as it contains 4 charcaters and at least other 2 charcaters for the end sequence "\n" which is contained in a string. Thus, I supposed that the number of bytes occupied by the first element of the array should be 6 and not 8.
Moreover, if I increase/decrease the number of charcaters contained in the first element of the array, the its size does not change.
Clearly, I am wrong. If somebody can explain me this functioning, I would really appreciate.
Thanks,
I wrote a simple program in order to understand the functioning of the function of the standard c++ library sizeof().
Wrong terminology. Please read n3337 (a C++ standard) and the wikipage on sizeof.
sizeof is a compile-time operator, not a function. If v is some variable, sizeof(v) only depends on the type of v and never on its value (in contrast, for most functions f, the value of f(v) depends upon the value of v).
And a good way to understand something about C++ is to refer to documents like standards or good web pages about it.
If somebody can explain me
Yes. Read a good book about C++. This one is written by the main designer of C++. Try to understand more and better the (difficult) semantics of C++. You could also study the source code of existing open source C++ compilers such as GCC or Clang/LLVM (thus effectively using one of your free software freedoms).
BTW, with a lot of pain you might find C++ implementations with sizeof(int) being 1 (e.g. for some DSP processors). On cheap 32 bits ARM processors (those in cheap mobile phones today, for instance; then you would probably use some cross-compiler) or on some Raspberry Pis (or perhaps some mainframes) you could have sizeof(array[0]) or sizeof(void*) being 4 even in 2019.
Let's break down the meaning of the somewhat confusing output values you see!
First, the sizeof(array) and sizeof(array[0]) (where your output method is fine). You have delared/defined array as an array of two char* values, each of which is a pointer. The size of a pointer on your system is 8 bytes, so the total size of array is: 8 * 2 = 16. For array[0]: this is a single pointer, so its size is simply 8 bytes.
Does all this make sense so far? If so, then let's look at the second part of your code …
The values for sizeof(char), sizeof(int), sizeof(float) and sizeof(double) are, on your system, in order, 1, 4, 4, and 8. These values are actually being output! However, as you are also outputting the return value of printf(), which is the number of characters it has written, you are getting the extra values, "2", "2", "2" and "1" inserted (in a confusing, and possibly undefined, order), for the four calls (the last one has no newline, so it's only one character; all others are one digit + newline = 2 characters).
Change the second part of your code as follows, to get the correct outputs:
printf("%zu\n", sizeof(char)); //1
printf("%zu\n", sizeof(int)); //4
printf("%zu\n", sizeof(float)); //4
printf("%zu\n", sizeof(double)); //8
I am initializing millions of classes that are of the following type
template<class T>
struct node
{
//some functions
private:
T m_data_1;
T m_data_2;
T m_data_3;
node* m_parent_1;
node* m_parent_2;
node* m_child;
}
The purpose of the template is to enable the user to choose float or double precision, with the idea being that by node<float> will occupy less memory (RAM).
However, when I switch from double to float the memory footprint of my program does not decrease as I expect it to. I have two questions,
Is it possible that the compiler/operating system is reserving more space than required for my floats (or even storing them as a double). If so, how do I stop this happening - I'm using linux on 64 bit machine with g++.
Is there a tool that lets me determine the amount of memory used by all the different classes? (i.e. some sort of memory profiling) - to make sure that the memory isn't being goobled up somewhere else that I haven't thought of.
If you are compiling for 64-bit, then each pointer will be 64-bits in size. This also means that they may need to be aligned to 64-bits. So if you store 3 floats, it may have to insert 4 bytes of padding. So instead of saving 12 bytes, you only save 8. The padding will still be there whether the pointers are at the beginning of the struct or the end. This is necessary in order to put consecutive structs in arrays to continue to maintain alignment.
Also, your structure is primarily composed of 3 pointers. The 8 bytes you save take you from a 48-byte object to a 40 byte object. That's not exactly a massive decrease. Again, if you're compiling for 64-bit.
If you're compiling for 32-bit, then you're saving 12 bytes from a 36-byte structure, which is better percentage-wise. Potentially more if doubles have to be aligned to 8 bytes.
The other answers are correct about the source of the discrepancy. However, pointers (and other types) on x86/x86-64 are not required to be aligned. It is just that performance is better when they are, which is why GCC keeps them aligned by default.
But GCC provides a "packed" attribute to let you exert control over this:
#include <iostream>
template<class T>
struct node
{
private:
T m_data_1;
T m_data_2;
T m_data_3;
node* m_parent_1;
node* m_parent_2;
node* m_child;
} ;
template<class T>
struct node2
{
private:
T m_data_1;
T m_data_2;
T m_data_3;
node2* m_parent_1;
node2* m_parent_2;
node2* m_child;
} __attribute__((packed));
int
main(int argc, char *argv[])
{
std::cout << "sizeof(node<double>) == " << sizeof(node<double>) << std::endl;
std::cout << "sizeof(node<float>) == " << sizeof(node<float>) << std::endl;
std::cout << "sizeof(node2<float>) == " << sizeof(node2<float>) << std::endl;
return 0;
}
On my system (x86-64, g++ 4.5.2), this program outputs:
sizeof(node<double>) == 48
sizeof(node<float>) == 40
sizeof(node2<float>) == 36
Of course, the "attribute" mechanism and the "packed" attribute itself are GCC-specific.
In addtion to the valid points that Nicol makes:
When you call new/malloc, it doesn't necessarily correspond 1 to 1 with a call the the OS to allocate memory. This is because in order to reduce the number of expensive syste, calls, the heap manager may allocate more than is requested, and then "suballocate" chunks of that when you call new/malloc. Also, memory can only be allocated 4kb at a time (typically - this is the minimum page size). Essentially, there may be chunks of memory allocated that are not currently actively used, in order to speed up future allocations.
To answer your questions directly:
1) Yes, the runtime will very likely allocate more memory then you asked for - but this memory is not wasted, it will be used for future news/mallocs, but will still show up in "task manager" or whatever tool you use. No, it will not promote floats to doubles. The more allocations you make, the less likely this edge condition will be the cause of the size difference, and the items in Nicol's will dominate. For a smaller number of allocations, this item is likely to dominate (where "large" and "small" depends entirely on your OS and Kernel).
2) The windows task manager will give you the total memory allocated. Something like WinDbg will actually give you the virtual memory range chunks (usually allocated in a tree) that were allocated by the run-time. For Linux, I expect this data will be available in one of the files in the /proc directory associated with your process.
This question already has answers here:
Do all pointers have the same size in C++?
(10 answers)
Closed 5 months ago.
Is the size of a pointer the same as the size as the type it's pointing to, or do pointers always have a fixed size? For example...
int x = 10;
int * xPtr = &x;
char y = 'a';
char * yPtr = &y;
std::cout << sizeof(x) << "\n";
std::cout << sizeof(xPtr) << "\n";
std::cout << sizeof(y) << "\n";
std::cout << sizeof(yPtr) << "\n";
What would the output of this be? Would sizeof(xPtr) return 4 and sizeof(yPtr) return 1, or would the 2 pointers actually return the same size?
The reason I ask this is because the pointers are storing a memory address and not the values of their respective stored addresses.
Function Pointers can have very different sizes, from 4 to 20 bytes on an x86 machine, depending on the compiler. So the answer is no - sizes can vary.
Another example: take an 8051 program. It has three memory ranges and thus has three different pointer sizes, from 8 bit, 16 bit, 24 bit, depending on where the target is located, even though the target's size is always the same (e.g., char).
Pointers generally have a fixed size, for ex. on a 32-bit executable they're usually 32-bit. There are some exceptions, like on old 16-bit windows when you had to distinguish between 32-bit pointers and 16-bit... It's usually pretty safe to assume they're going to be uniform within a given executable on modern desktop OS's.
Edit: Even so, I would strongly caution against making this assumption in your code. If you're going to write something that absolutely has to have a pointers of a certain size, you'd better check it!
Function pointers are a different story -- see Jens' answer for more info.
On 32-bit machine sizeof pointer is 32 bits ( 4 bytes), while on 64 bit machine it's 8 byte. Regardless of what data type they are pointing to, they have fixed size.
To answer your other question. The size of a pointer and the size of what it points to are not related. A good analogy is to consider them like postal addresses. The size of the address of a house has no relationship to the size of the house.
Pointers are not always the same size on the same architecture.
You can read more on the concept of "near", "far" and "huge" pointers, just as an example of a case where pointer sizes differ...
http://en.wikipedia.org/wiki/Intel_Memory_Model#Pointer_sizes
They can be different on word-addressable machines (e.g., Cray PVP systems).
Most computers today are byte-addressable machines, where each address refers to a byte of memory. There, all data pointers are usually the same size, namely the size of a machine address.
On word-adressable machines, each machine address refers instead to a word larger than a byte. On these, a (char *) or (void *) pointer to a byte of memory has to contain both a word address plus a byte offset within the addresed word.
http://docs.cray.com/books/004-2179-001/html-004-2179-001/rvc5mrwh.html
Recently came upon a case where this was not true, TI C28x boards can have a sizeof pointer == 1, since a byte for those boards is 16-bits, and pointer size is 16 bits. To make matters more confusing, they also have far pointers which are 22-bits. I'm not really sure what sizeof far pointer would be.
In general, DSP boards can have weird integer sizes.
So pointer sizes can still be weird in 2020 if you are looking in weird places
The size of a pointer is the size required by your system to hold a unique memory address (since a pointer just holds the address it points to)
I'm trying to understand the amount of bytes occupied by an instance of std::vector. The following code:
vector <int>uno;
uno.push_back(1);
uno.push_back(1);
cout <<"1: "<< sizeof(uno)<<" bytes"<<endl;
cout << endl;
vector <bool>unos;
unos.push_back(true);
cout <<"2: "<< sizeof(unos)<<" bytes"<<endl;
cout << endl;
gives me this output:
1: 12 bytes
2: 20 bytes
Can someone explain me why the size of the vector<bool> has more bytes than the vector<int>?. And what is the correct way to measure the size in bytes of an vector instance... by adding the size of every member in the vector?
In C++, the sizeof operator is always evaluated at compile time, so every vector<T> will have the same size (unless vector<T> is a specialization like vector<bool>).
In case you are wondering about the 12 bytes, that is probably the size of 3 pointers, or alternatively, the size of a pointer and an element count and a capacity. The real data is never stored inside the vector.
If you want to know how much memory is used total, a good approximation is:
sizeof(std::vector<T>) + my_vector.capacity() * sizeof(T)
This is only an approximation because it does not take into account book-keeping data on the heap.
std::vector<bool> is larger since it is more complicated than std::vector<int>. The current C++ standard specifies that the vector<bool> data should be bit-packed. This requires some additional bookkeeping, and gives them a slightly different behavior than the normal std::vector<T>.
This different behavior of std::vector<bool> is very likely to be removed in the upcoming C++0x standard.