Knowing the size in bytes of a pointer

Started by
11 comments, last by RobTheBloke 16 years, 8 months ago

int main(int argc, char *argv[])
{
    int *num;
    num = new int[10];
    
    for(int i=0;i<10;i++)
    {
            num = 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?
Advertisement
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.
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.

Steven Yau
[Blog] [Portfolio]

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
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;    }        cout << num.size() * sizeof(int) << "\n";        system("PAUSE");    return EXIT_SUCCESS;}


Edd
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.
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)
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
I'm willing to bet that libJpeg already has the functionality to deal with the size of the image.
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

This topic is closed to new replies.

Advertisement