This question already has answers here:
Why the libc++ std::vector internally keeps three pointers instead of one pointer and two sizes?
(3 answers)
Closed 1 year ago.
#include <iostream>
#include <vector>
int main(int argc, char const *argv[])
{
std::vector<int> a(32768, 0);
std::cout << "Size " << sizeof a << "\nCapacity " << a.capacity() << "\nElements " << a.size();
return 0;
}
for this program im getting the output:
Size 24
Capacity 32768
Elements 32768
using valgrind i calculated heap usage which is:
132096 bytes
that is (32768 x 4 bytes) + 24 bytes
im interested in how are these 24 bytes used by vector a
As addressed in the comments by Kamil, a std::vector keeps track of three pointers internally. One pointer to the begin, one to end and one to the end of allocated memory (see stack post). Now, the size of a pointer should be 8 bytes on any 64-bit C/C++ compiler so, 3 * 8 bytes = 24 bytes (see wiki).
Related
This is the code for testing my question.
#include <iostream>
#include <stack>
using namespace std;
int main(){
int num;
int Array[1];
stack<int> Stack;
cout << "Int size " << sizeof(num) <<endl; // Output: Int size 4
cout << "Array size " << sizeof(num) <<endl; // Output: Array size 4
cout << "Stack size " << sizeof(Stack) <<endl; // Output: Stack size 80
return 0;
}
I'm trying to understand about memory space allocation. Normally int memory size is 4 bytes. But, when I initialize an Stack of int data-type in std::stack then the Stack size is 80 bytes.
Should it 4? Why is std::stack taking 80 bytes? Or what is actually inside of stack for being the size 80 bytes?
sizeof gets the static size of the object/type. stack dynamically allocates memory for its elements. So, there is no correlation between size of the elements and size of stack in general. So, why is it 80 bytes? This is highly implementation specific. Size of stack is usually the same as the underlying container. By default, the underlying container is a std::deque, so that's where we must have a look. I checked libstdc++ specifically, and it seems to have 1 pointer, 1 size_t for size and 2 iterators like so:
struct _Deque_impl_data
{
_Map_pointer _M_map;
size_t _M_map_size;
iterator _M_start;
iterator _M_finish;
//...
(std::deque derives from _Deque_base which has a single member of type _Deque_impl_data)
Pointer and integer are 8 bytes, the iterators are 32 bytes. This adds up to 80 bytes. I didn't further investigate, but since deque is a more complex structure, it's only natural that it needs some memory for its own book-keeping.
You maybe confusing sizeof(Stack) with Stack.size() here. The sizeof operator returns the total size of the class object, which, in the case of std::stack includes (of necessity) a number of internal data and control variables (padding the size out to, in your case, 80 bytes). However, a call to Stack.size() will return the number of items currently on the stack.
These 'internal variables' will include such things as a pointer to the allocated memory (likely 8 bytes), a value recording the current element count (also likely to be 8 bytes) and a number of other pointers and counters, to aid in manipulation of the stack and optimization of access to the contained data, such as the current capacity of the allocated space, etc.
The following modified code shows the difference:
#include <iostream>
#include <stack>
using namespace std;
int main()
{
int num;
int Array[1];
stack<int> Stack;
cout << "Int size " << sizeof(num) << endl; // Int size 4
cout << "Array size " << sizeof(Array) << endl; // Array size 4 (1 "int" element)
cout << "Stack size " << sizeof(Stack) << endl; // Size of a "std::stack<int>" instance
cout << "Stack size " << Stack.size() << endl; // Size (# entries) of stack = 0 (empty)
return 0;
}
I have a question about the answer provided by
#dan04. What is aligned memory allocation?
In particular, if I have something like this:
int main(){
int num; // 4byte
char s; // 1byte
int *ptr;
}
If I have a 32 bit machine, do you think it would still be padding at the data by default?
In the previous question, it was asked about struct, and I am asking about variables declared in main.
update:
a = 2 bytes
b = 4 bytes
c = 1 byte
d = 1 byte
0 1 2 3 4 5 6 7
|a|a|b|b|b|b|c|d| bytes
| | | words
There are no rules for this. It depends on the implementation you are using. Further it may change depending on compiler options. The best you can do is to print the address of each variable. Then you can see how the memory layout is.
Something like this:
int main(void)
{
int num;
char s;
int *ptr;
printf("num: %p - size %zu\n", (void*)&num, sizeof num);
printf("s : %p - size %zu\n", (void*)&s, sizeof s);
printf("ptr: %p - size %zu\n", (void*)&ptr, sizeof ptr);
return 0;
}
Possible output:
num: 0x7ffee97fce84 - size 4
s : 0x7ffee97fce83 - size 1
ptr: 0x7ffee97fce88 - size 8
Also notice that in case you don't take the address (&) of a variable, the compiler may optimize your code so that the variable is never put into memory at all.
In general the alignment is typically made to get the best performance out of the HW platform used. That typically imply that variables are aligned to their size or at least 4 byte aligned for variables with size greater than 4.
Update:
OP gives a specific layout example in the update and asks if that layout can/will ever happen.
Again the answer is: It is implementation dependent
So in principle it could happen on some specific system. That said I doubt that it will happen on any mainstream system.
There is another code example compiled with gcc -O3
int main(void)
{
short s1;
int i1;
char c1;
int i2;
char c2;
printf("s1: %p - size %zu\n", (void*)&s1, sizeof s1);
printf("i1: %p - size %zu\n", (void*)&i1, sizeof i1);
printf("c1: %p - size %zu\n", (void*)&c1, sizeof c1);
printf("i2: %p - size %zu\n", (void*)&i2, sizeof i2);
printf("c2: %p - size %zu\n", (void*)&c2, sizeof c2);
return 0;
}
Output from my system:
s1: 0x7ffd222fc146 - size 2 <-- 2 byte aligned
i1: 0x7ffd222fc148 - size 4 <-- 4 byte aligned
c1: 0x7ffd222fc144 - size 1
i2: 0x7ffd222fc14c - size 4 <-- 4 byte aligned
c2: 0x7ffd222fc145 - size 1
Notice how the location in memory differs from the order variables was defined in the code. That ensures a good alignment.
Sorting by address:
c1: 0x7ffd222fc144 - size 1
c2: 0x7ffd222fc145 - size 1
s1: 0x7ffd222fc146 - size 2 <-- 2 byte aligned
i1: 0x7ffd222fc148 - size 4 <-- 4 byte aligned
i2: 0x7ffd222fc14c - size 4 <-- 4 byte aligned
So again to answer the update-question:
On most systems I doubt you'll see a 4 byte variable being placed at address xxx2, xxx6 or xxxa, xxxe. But still, systems may exist where that could happen.
It's quite hard to exactly predict, but there's certainly some padding going on.
Take these two codes for example (I run them on Coliru, 64bit machine)
#include<iostream>
#include <vector>
using namespace std;
//#pragma pack(push,1)
int main(){
int num1(5); // 4byte
int num2(3); // 4byte
char c1[2];
c1[0]='a';
c1[1]='a';
cout << &num1 << " " << &num2 << " " << endl;
cout << sizeof(c1) << " " << &c1 << endl;
}
//#pragma pack(pop)
#include<iostream>
#include <vector>
using namespace std;
//#pragma pack(push,1)
int main(){
int num1(5); // 4byte
int num2(3); // 4byte
char c1[1];
c1[0]='a';
cout << &num1 << " " << &num2 << " " << endl;
cout << sizeof(c1) << " " << &c1 << endl;
}
//#pragma pack(pop)
The first program outputs:
0x7fff3e1f9de8 0x7fff3e1f9dec
2 0x7fff3e1f9de0
While the second program outputs:
0x7fffdca72538 0x7fffdca7253c
1 0x7fffdca72537
You can definitely notice that there's a padding being made in the first program, looking at the addresses we can see that:
First program: CHAR | CHAR | 6-BYTE PADDING | INT | INT
Second program: CHAR | INT | INT
So for the basic question, yes it is probably padding by default.
I also tried to use pragma pack to avoid padding, and in contrast to the struct case, I didn't manage to make it avoid padding, since the outputs were exactly the same.
This question already has answers here:
Pointer subtraction confusion
(8 answers)
Closed 6 years ago.
I have a puzzling question (at least for me)
Say I declare an integer array:
int arr[3];
Conceptually, what happens in the memory is that, at compile time, 12 bytes are allocated to store 3 consecutive integers, right? (Here's an illustration)
Based on the illustration, the sample addresses of
arr[0] is 1000,
arr[1] is 1004, and
arr[2] is 1008.
My question is:
If I output the difference between the addresses of arr[0] and arr[1]:
std::cout << &arr[1] - &arr[0] << std::endl;
instead of getting 4,
I surprisingly get 1.
Can anybody explain why it resulted to that output?
PS: On my computer, an int is 4 bytes.
Pointer arithmetic automatically divides the value by the size of the base type so this is not surprising at all since one would expect to get 4 / 4 which is 1. Cast to unsignd char * to see the difference.
#include <iostream>
int
main(void)
{
int arr[2];
std::cout << &arr[1] - &arr[0] << std::endl;
std::cout << reinterpret_cast<unsigned char *>(&arr[1]) -
reinterpret_cast<unsigned char *>(&arr[0]) << std::endl;
return 0;
}
I'm working on an Arduino project. I'm trying to pass a byte pointer to a function, and let that function calculate the size of the data that the pointer refers to. But when I let the pointer refer to a byte, sizeof() returns 2. I wrote the following snippet to try to debug:
byte b;
byte *byteptr;
byteptr = &b;
print("sizeof(b): ");
println(sizeof(b));
print("sizeof(*byteptr) pointing to byte: ");
println(sizeof(*byteptr));
print("sizeof(byteptr) pointing to byte: ");
println(sizeof(byteptr));
the printed result is:
sizeof(b): 1
sizeof(*byteptr) pointing to byte: 1
sizeof(byteptr) pointing to byte: 2
So the size of a byte is 1, but via the pointer it's 2??
It appears that on Arduino, pointers are 16 bit. I believe your confusion stems from what * means in this context.
sizeof(*byteptr) is equivalent to the sizeof(byte). The * does not indicate a pointer type, it indicates dereferencing the pointer stored in byteptr. Ergo, it is 1 byte, which you would expect from the type byte.
sizeof(byteptr) does not dereference the pointer, and as such, is the size of the pointer itself, which on this system seems to be 2 bytes/16 bits.
Consider the following:
#include "iostream"
using namespace std;
int main()
{
char a = 1;
char* aP = &a;
cout << "sizeof(char): " << sizeof(char) << endl;
cout << "sizeof(char*): " << sizeof(char*) << endl;
cout << "sizeof(a): " << sizeof(a) << endl;
cout << "sizeof(aP): " << sizeof(aP) << endl;
cout << "sizeof(*aP): " << sizeof(*aP) << endl;
}
Output (on a 64 bit OS/compiler):
sizeof(char): 1
sizeof(char*): 8
sizeof(a): 1
sizeof(aP): 8
sizeof(*aP): 1
#Maseb I think you've gotten a good discussion of the differences between the size of a dereferenced pointer and the actual size of the pointer itself. I'll just add that the sizeof(byte_pointer) must be large enough so that every address of memory space where a byte value could potentially be stored will fit into the pointer's memory width. For example, if there 32,000 bytes of storage on your Arduino then you could potentially have a pointer that needs to point to the address 32,000. Since 2^15 is about 32,000 you need 14 or 15 bits to create a unique address for each memory storage location. We set pointer address space length to blocks of four bits. Therefore, your Arduino has a 16bit address space for pointers and sizeof(byte_pointer) is 2 bytes, or 16 bits.
With that said, I'll go ahead an answer your other question too. If you need to pass an array and a size, just create your own struct that includes both of those data elements. Then you can pass the pointer to this templated struct which includes the size (This is the basic implementation for the C++ Array container).
I've written the short code sample below to demonstrate how to create your own template for an array with a size element and then use that size element to iterate over the elements.
template<int N>
struct My_Array{
int size = N;
int elem[N];
};
//create the pointer to the struct
My_Array<3>* ma3 = new My_Array<3>;
void setup() {
//now fill the array element
for(int i=0; i < ma3->size; i++) {
ma3->elem[0]=i;
}
Serial.begin(9600);
//now you can use the size value to iterate over the elements
Serial.print("ma3 is this big: ");
Serial.println(ma3->size);
Serial.println("The array values are:");
Serial.print("\t[");
for(int i=0; i<ma3->size; i++) {
Serial.print(ma3->elem[i]);
if(i < ma3->size-1) Serial.print(", ");
}
Serial.println("]");
}
void loop() {
while(true) { /* do nothing */ }
}
This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 9 years ago.
Hi I have an array defined in my header filed
private:
Customer** customerListArray;
In my cpp file I set it as following,
customerListArray = new Customer* [data.size()];
cout << "arr size " << data.size() << "\n";
cout << "arr size " << sizeof(customerListArray) << "\n";
However data.size() is 11900, but sizeof(customerListArray) array is always 4. I've tried replacing data.size() with 100 and still I get 4.
What am I doing wrong here?
Thank you.
Pointers are always of fixed size and the OP is using pointer. For sizeof() to return the actual length of an array, you have to declare an array and pass it's name to sizeof().
int arr[100];
sizeof(arr); // This would be 400 (assuming int to be 4 and num elements is 100)
int *ptr = arr;
sizeof(ptr); // This would be 4 (assuming pointer to be 4 bytes on this platform.
It is also important to note that sizeof() returns number of bytes and not number of elements
because customerListArray is a pointer
sizeof() returns the size in bytes of an element, in this case your 'customer**' is 4 bytes in size.
See this page for reference on sizeof().