Sign in to follow this  

Knowing the size in bytes of a pointer

This topic is 3777 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

int main(int argc, char *argv[])
{
    int *num;
    num = new int[10];
    
    for(int i=0;i<10;i++)
    {
            num[i] = i;
    }
    
    cout << sizeof(num) << "\n";
    
    system("PAUSE");
    return EXIT_SUCCESS;
}


when i run this program the sizeof statement returns 4. I thaught it would return 10*4bytes(32 bit int) because i read that sizeof returns the number of bytes something uses. If i dont know the size of an array at runtime, is there a way to properly get the size in bytes the array takes up in memory?

Share this post


Link to post
Share on other sites
Use std::vector anytime you would be tempted to use new[] and delete[]. This will help you, for example in your program you forgot to call delete [] so you leak memory.

To get the byte size of a vector's contents use this:

template< class Type>
unsigned vector_size( const std::vector<Type> &v ) {
return v.size() * sizeof(Type);
}



Remember, sizeof() returns the size in bytes of the type you give it. You passed it "num" which is of type int*. C++ does not know that num points to anything in particular. This is because sizeof() is a compile-time constant. The array you allocate only exists at runtime.

Share this post


Link to post
Share on other sites
It is returning the size of the pointer not the size of the data that it is pointing to. If you are using C++ then use vector template class from the standard library instead of dynamically allocating arrays. Much safer and helps prevent memory leaks like the one you have already in your code.

Share this post


Link to post
Share on other sites
Quote:
Original post by hahaha
It was just an example. I cant use an std::vector in this code. I have to use an unsigned char array because of the file im working with

That sounds somewhat suspicious. I don't see how working with a particular file should stop you from using a vector?

Anyway, there's no portable way of getting the number of objects or bytes that a new[]-ed pointer points at. You will have to keep a 'size' variable around alongside the pointer.

But again, we come back to std::vector<>, which can handle this for you, is exception safe and guarantees resource proper clean up.


int main(int argc, char *argv[])
{
std::vector<int> num(10);

for(int i=0;i<10;i++)
{
num[i] = i;
}

cout << num.size() * sizeof(int) << "\n";

system("PAUSE");
return EXIT_SUCCESS;
}




Edd

Share this post


Link to post
Share on other sites
Quote:
Original post by hahaha
It was just an example. I cant use an std::vector in this code. I have to use an unsigned char array because of the file im working with
You could always abuse the data itself, but it's extremely ugly and it's much preferable to go with vector, or just keep a size array around:

int* alloc_array(int count)
{
int* n = new int[count + 1];
*n = count;
return n+1;
}

int array_size(int* array)
{
return array[-1];
}

void free_array(int* array)
{
delete[] array-1;
}


Like I said, it's extremely hacky - you store the size of the array in the first element, and then return a pointer to the next element. But this is just asking for trouble (This is actually something along the lines of how memoey managers [including the debug CRT] work).

It's worth noting that most functions that take an array will take a pointer and a length (E.g. most Win32 functions) - this is the way you should be doing things if you can't use vector.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Steve
*** Source Snippet Removed ***
Like I said, it's extremely hacky - you store the size of the array in the first element, and then return a pointer to the next element. But this is just asking for trouble (This is actually something along the lines of how memoey managers [including the debug CRT] work).


wouldn't work with arrays that are not ints ;) (and since the OP wants an array of chars, won't work at all). As previously mentioned, you always need to store the array size with a dynamic array, so you tend to end up with something like this :


struct IntArray
{
IntArray() : mSize(0), mData(0) {}
~IntArray() { delete [] mData; }
IntArray(const IntArray& rhs) {
mSize = rhs.mSize;
mData = new int[mSize];
memcpy(mData,rhs.mData,mSize*sizeof(int));
}
int& operator[](const unsigned index) {
assert(index<mSize);
return mData[index];
}
const int& operator[](const unsigned index) const {
assert(index<mSize);
return mData[index];
}
void resize(unsigned num) {
int* temp = new int[num];
if(num<mSize) {
memcpy(temp,mData,num*sizeof(int));
}
else {
memcpy(temp,mData,mSize*sizeof(int));
}
delete [] mData;
mData=temp;
mSize=num;
}
unsigned size() const {
return mSize;
}
private:
unsigned mSize;
int* mData;
};




which then gets templated to work for any data type :


template<typename T>
struct Array
{
Array() : mSize(0), mData(0) {}
~Array() { delete [] mData; }
Array(const Array<T>& rhs) {
mSize = rhs.mSize;
mData = new T[mSize];
memcpy(mData,rhs.mData,mSize*sizeof(T));
}
T& operator[](const unsigned index) {
assert(index<mSize);
return mData[index];
}
const T& operator[](const unsigned index) const {
assert(index<mSize);
return mData[index];
}
void resize(unsigned num) {
T* temp = new T[num];
if(num<mSize) {
memcpy(temp,mData,num*sizeof(T));
}
else {
memcpy(temp,mData,mSize*sizeof(T));
}
delete [] mData;
mData=temp;
mSize=num;
}
unsigned size() const {
return mSize;
}
private:
unsigned mSize;
T* mData;
};




which then basically gives you std::vector, so you might as well just use std::vector rather than faffing around with anything else.... (the template Array class above, doesn't work for types that don't provide a default constructor for example.... std::vector however will work properly in this case)

Share this post


Link to post
Share on other sites
The thing is im trying to keep track of a jpeg files data size. Im using LibJpeg and i have know idea where to start in changing the source so that i can keep track of the data size

Share this post


Link to post
Share on other sites
Quote:
Original post by hahaha
The thing is im trying to keep track of a jpeg files data size. Im using LibJpeg and i have know idea where to start in changing the source so that i can keep track of the data size


Take the time to read the docs, it's all in there. You'll need to provide your own "source manager" implementation, IIRC. In fact you don't even need to do that. Once you've used the library to read the JPEG header, you can allocate enough storage for the raster in one go i.e. create an std::vector<> with the appropriate number of elements.

Or, you can use an existing higher level library such as jpegxx (shameless plug), which is based on libjpeg:


std::vector<unsigned char> pixel_bytes;

std::ifstream infile("my_image.jpg", std::ios::binary);

jpegxx::raster_details d = jpegxx::read_image(infile, std::back_inserter(pixel_bytes));



pixel_bytes will be filled with rgb or greyscale pixel components. It will expand as necessary. You can query the image size using the raster_details object, d.

If you really do need the actual size of the jpeg *file*, once read, you can call infile.tellg(). But if the file size is what you need, why not just query the size of the file using the appropriate API for your OS?

Edd

Share this post


Link to post
Share on other sites
Let's try it with a couple of slight renamings (and minor style corrections, and actually cleaning up the memory you allocated... sheesh. You do know there's a For Beginners forum? Sorry for any ego deflation...)

Quote:
Original post by hahaha

int main(int argc, char *argv[])
{
typedef int house;
const int street_length = 10;
house *finger = new house[street_length]; // late edit for consistency

// initialize houses...

cout << sizeof(finger) << "\n";

delete[] finger;
}



When we run this, it of course returns the size of my finger, not the size of the street, because, well, I asked it for the size of my finger.

4 bytes *is* the size of your pointer. What you are somehow imagining you could get is the size of the pointed-at thing.

Quote:
If i dont know the size of an array allocation at runtime, is there a way to properly get the size in bytes the array takes up in memory?


First, please note that "an array" you allocate with new[] is fundamentally different from an ordinary array, which is why I insist on using slightly different terminology.

But anyway, you do know the size, because you allocated it. The size is the size of the type you allocated, times the number of elements you allocated. The way you get that size is to do the multiplication.


cout << sizeof(house) * street_length << "\n";


[Edited by - Zahlman on August 13, 2007 10:00:03 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by hahaha
No i need to know the size of the pixel data.


size = width * height * bytes_per_pixel;

if image is RGB, bytes_per_pixel = 3
if image is RGBA, bytes_per_pixel = 4

don't think jpegs support 32bit images though, so probably just 3 * width * height. Won't be able to tell you the size of that data after it's compressed, but there really should be a function to do that.

Share this post


Link to post
Share on other sites

This topic is 3777 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this