Calculating the size of an array

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Nepomuk
    Recognized Expert Specialist
    • Aug 2007
    • 3111

    Calculating the size of an array

    Hi!
    I've read, that in C++ there's no predefined method, to calculate the size of an array. However, it's supposed to work with[code=cpp]sizeof(array)/sizeof(array[0])[/code]Now, this does work in some situations, but not in others. Here's what I mean:[code=cpp]#include <iostream>

    int length(int * array){return sizeof(array)/sizeof(array[0]);}

    int main()
    {
    int array1[4] = {3,2,1,0};
    std::cout << "Length of array1: " << sizeof(array1)/sizeof(array1[0]) << "\n"
    << "length(arr ay1) = " << length(array1)
    << endl;
    }
    [/code]The output is:
    Code:
    Length of array1: 4
    length(array1) = 1
    Now, I'm guessing, that my function length is just checking the size of the pointer to the first element of the array. My question is: Is there any method, to determine the size of an array, after this has been passed to a function? I'd hate to have to pass on that kind of information as an argument to every function, that needs the size of the array, manually.

    Greetings,
    Nepomuk
  • oler1s
    Recognized Expert Contributor
    • Aug 2007
    • 671

    #2
    I'd hate to have to pass on that kind of information as an argument to every function, that needs the size of the array, manually.
    Sorry. Pass the information. Ever see C stdlib functions like strncpy? Guess why they ask you to manually tell them the size of the array.

    Comment

    • arnaudk
      Contributor
      • Sep 2007
      • 425

      #3
      You could use some terminating element in your array, then your length function count the number of elements until the terminating element. C strings are character arrays that are null terminated in this manner.

      Comment

      • Nepomuk
        Recognized Expert Specialist
        • Aug 2007
        • 3111

        #4
        Originally posted by oler1s
        Sorry. Pass the information. Ever see C stdlib functions like strncpy? Guess why they ask you to manually tell them the size of the array.
        Grrr... Why can't C++ be a bit more like Java in that way... :-(
        Originally posted by arnaudk
        You could use some terminating element in your array, then your length function count the number of elements until the terminating element. C strings are character arrays that are null terminated in this manner.
        That's a bit difficult, if it's an array of integers, because that would mean, that I can't use some specific numbers.
        But how about something like this:[code=cpp]class Array<T>
        {
        private:
        unsigned int length = 0;

        public:
        T myArray[];

        void setArray(int array*, unsigned int le)
        {
        myArray = array;
        length = le;
        }

        T* getArray()
        {
        return myArray;
        }

        unsigned int getLength()
        {
        if(length==0) length = sizeof(array)/sizeof(array[0]);
        return length;
        }
        }
        [/code]There are probably errors in that code, but the idea should be clear: It would allow you to set an array directly (as it is public) or use the setArray method, giving the length. Of course, methods to access the elements would be needed to.

        I would guess, that I'm not the first person to have this idea and there's probably something like that in std - does anyone know of such a class?

        Greetings,
        Nepomuk

        Comment

        • Laharl
          Recognized Expert Contributor
          • Sep 2007
          • 849

          #5
          The class you're looking for is the std::vector, defined for your convenience in <vector>.

          C/C++ arrays don't do bounds checking for overhead reasons, as doing so increases the time for every array access a fair bit. Thus, they expect the programmer to handle these things for himself. It can be annoying, but there you have it.

          Comment

          • Nepomuk
            Recognized Expert Specialist
            • Aug 2007
            • 3111

            #6
            OK, thank you - I'll try using vectors. I knew about them (well, tried using them a while ago), but I thought, they were just dynamic arrays and never thought about using them that way. Well, you live and learn! :-)

            Greetings,
            Nepomuk

            Comment

            • oler1s
              Recognized Expert Contributor
              • Aug 2007
              • 671

              #7
              Use either Boost.Array (fixed sized) or std::vector (dynamic size)

              Comment

              • Nepomuk
                Recognized Expert Specialist
                • Aug 2007
                • 3111

                #8
                Originally posted by oler1s
                Use either Boost.Array (fixed sized) or std::vector (dynamic size)
                Thanks, the Boost.Array looks just right! But I might still use the vector. We'll see...

                Greetings,
                Nepomuk

                Comment

                • JosAH
                  Recognized Expert MVP
                  • Mar 2007
                  • 11453

                  #9
                  Originally posted by nepomuk
                  Thanks, the Boost.Array looks just right! But I might still use the vector. We'll see...

                  Greetings,
                  Nepomuk
                  Consider the Boost arrays equivalent to Java's arrays; the vector is more like an
                  ArrayList in Java.

                  kind regards,

                  Jos

                  Comment

                  • fauxanadu
                    New Member
                    • Mar 2007
                    • 60

                    #10
                    Array Class

                    You could use vectors or you could just create a class to wrap the type of array you want. For instance, for an integer array you could use:

                    IntArray.h
                    Code:
                    #define NULL 0
                    
                    #include <stdio.h>
                    
                    class IntArray
                    {
                    	private:
                    
                    	protected:
                    		//This stores the array
                    		int* iArray;
                    		//This stores the size of the array
                    		int size;
                    	
                    	public:
                    		IntArray();
                    		IntArray(int);
                    		IntArray(IntArray&);
                    		void delArray(void);
                    		int* getArray(void);
                    		void initArray(int);
                    		void setArray(int);
                    		int sizeOf(void);
                    };
                    
                    //Sets the array to NULL if no argument is provided
                    IntArray::IntArray(void)
                    {
                    	IntArray::iArray = NULL;
                    }
                    
                    //Sets the size and allocates memory for the array
                    IntArray::IntArray(int size)
                    {
                    	IntArray::iArray = new int[size];
                    	IntArray::size = size;
                    }
                    
                    //Copies an already existing IntArray
                    IntArray::IntArray(IntArray &copy)
                    {
                    	int i;
                    
                    	IntArray::size = copy.sizeOf();
                    	IntArray::iArray = new int[IntArray::size];
                    
                    	for(i = 0; i < IntArray::size; i++)
                    	{
                    		IntArray::iArray[i] = copy.getArray()[i];
                    	}
                    }
                    
                    //Clears the arrays memory
                    void IntArray::delArray(void)
                    {
                    	IntArray::iArray = NULL;
                    	IntArray::size = 0;
                    }
                    
                    //Returns the array
                    int* IntArray::getArray(void)
                    {
                    	return IntArray::iArray;
                    }
                    
                    //Initializes the array if it has not already been initialized
                    void IntArray::initArray(int size)
                    {
                    	if(iArray == NULL)
                    	{
                    		IntArray::iArray = new int[size];
                    		IntArray::size = size;
                    	}
                    }
                    
                    //Deletes the existing array if it exists and re-initializes the array
                    void IntArray::setArray(int size)
                    {
                    	if(iArray != NULL)
                    	{
                    		delete IntArray::iArray;
                    		IntArray::iArray = NULL;
                    	}
                    
                    	IntArray::iArray = new int[size];
                    	IntArray::size = size;
                    }
                    
                    //returns the size of the array
                    int IntArray::sizeOf(void)
                    {
                    	return IntArray::size;
                    }
                    For a float array, simply change the apropriate ints to floats in the class.

                    Here is an example of it in use:

                    Test.cpp
                    Code:
                    #include "IntArray.h"
                    #include <stdio.h>
                    
                    #define BASE  0
                    #define MULT  2
                    #define TOP  10
                    #define NEW  12
                    #define NEWS 10
                    #define NEWL 11
                    
                    int main(void)
                    {
                    	int      i;
                    	IntArray *myFirstArray;
                    	IntArray *mySecondArray;
                    
                    	//Creates an array of 10 ints
                    	myFirstArray = new IntArray(10);
                    
                    	//Sets each element equal to its element number times 2
                    	for (i = BASE; i < TOP; i++)
                    	{
                    		myFirstArray->getArray()[i] = i * MULT;
                    	}
                    
                    	//Copies the first array
                    	mySecondArray = new IntArray(*myFirstArray);
                    
                    	//Multiplies each element of the second array by 2
                    	for (i = BASE; i < TOP; i++)
                    	{
                    		mySecondArray->getArray()[i] = mySecondArray->getArray()[i] * MULT;
                    	}
                    
                    	//Outputs the sizes and values of each array
                    	printf("\n\nSize Of");
                    	printf("\n1st Array: %-2i    2nd Array: %-2i", myFirstArray->sizeOf(), mySecondArray->sizeOf());
                    	printf("\n\nValues:");
                    	printf("\n 1st     2nd");
                    
                    	for (i = BASE; i < TOP; i++)
                    	{
                    		printf("\n%-4i    %-4i", myFirstArray->getArray()[i], mySecondArray->getArray()[i]);
                    	}
                    
                    	printf("\n\nReinitialize 2nd Array");
                    
                    	//Reinitializes the second array
                    	mySecondArray->setArray(NEW);
                    	
                    	//Sets new values for each element of the now 12 element second array
                    	for (i = BASE; i < NEW; i++)
                    	{
                    		mySecondArray->getArray()[i] = i * i * MULT;
                    	}
                    
                    	//Outputs the sizes and values of each array
                    	printf("\n\nSize Of");
                    	printf("\n1st Array: %-2i    2nd Array: %-2i", myFirstArray->sizeOf(), mySecondArray->sizeOf());
                    	printf("\n\nValues:");
                    	printf("\n 1st     2nd");
                    
                    	for (i = BASE; i < TOP; i++)
                    	{
                    		printf("\n%-4i    %-4i", myFirstArray->getArray()[i], mySecondArray->getArray()[i]);
                    	}
                    	printf("\n        %-4i", mySecondArray->getArray()[NEWS]);
                    	printf("\n        %-4i", mySecondArray->getArray()[NEWL]);
                    
                    	//Clears the first array
                    	myFirstArray->delArray();
                    
                    	//Outputs the sizes and values of each array
                    	printf("\n\nSize Of");
                    	printf("\n1st Array: %-2i    2nd Array: %-2i", myFirstArray->sizeOf(), mySecondArray->sizeOf());
                    }
                    BTW, arrays in Java were implimented as a class similarly to this, only in Java it is pre-written for you.
                    Last edited by fauxanadu; Jul 8 '08, 06:01 PM. Reason: Hit submit too early

                    Comment

                    • Laharl
                      Recognized Expert Contributor
                      • Sep 2007
                      • 849

                      #11
                      Or, as the OP suggested in an earlier post, you could use templates so that you don't need eighteen different versions of nearly identical classes. Also, <stdio.h> is deprecated in C++, use <cstdio> instead.

                      Comment

                      • fauxanadu
                        New Member
                        • Mar 2007
                        • 60

                        #12
                        Despite it being depricated, it is still in rather common use (<stdio.h> that is).

                        And as for templates, bleh. It makes all the code ugly with all those damned angled brackets and even longer names. You save time on the front end by not copying and pasting the code a few times for each type, but then you lose it on the backend having to type all those damn <double>s, <int>s and <whathaveyou> s on the backend everytime you use it your template.

                        Plus, in regards to templates, a float and int are not always going to have the same member functions, so it would probably, in all honesty, be best to impliment it as a inherited heirarchy (IntArray, FloatArray, DoubleArray, et cetera, inherit NumberArray which, if you really have alot of time, could inherit ObjectArray or such). That would probably be the best idea.
                        Last edited by fauxanadu; Jul 8 '08, 06:12 PM. Reason: Added though

                        Comment

                        • oler1s
                          Recognized Expert Contributor
                          • Aug 2007
                          • 671

                          #13
                          fauxanadu, I was going to say "That's a funny joke". Then I actually looked at the code you wrote above, and came to two conclusions. You are either making a very elaborate bad joke, or you an utterly horrible C programmer who started picking up C++ syntax without learning how to actually use C++.

                          If you fall into the unfortunate latter case, the best thing you can do is to temporarily drop C and C++, and pick a very high level language to work with. At that point, poor programming practices will stick out very sorely, and you'll be forced to correct yourself. At which point you may then consider returning to C++.

                          Comment

                          • fauxanadu
                            New Member
                            • Mar 2007
                            • 60

                            #14
                            A) That code was written in about 5 minutes. Do better in less then we'll talk about structure. (You did mean structure, right? Because there is nothing wrong with the syntax.)

                            B) Each person has their coding preference. Mine is against templates. They are, to say the least, ugly and make the code far more difficult to read. There are many paths to produce the same result.

                            C) My job description requires that I produce solutions for my employer in VB, Java, C++, and Assembly depending on the situation. (I'll simplify this point for you: I program in high level, high-ish leveled, medium leveled, and low-leveled languages). My reviews are always positive and I have nothing but praise from the higher ups about my results. So as you can see, your point is both flawed and meaningless.

                            D) As it stands, I gave a solution to the above stated problem, someone stated an opinion about my code, I responded with my opinion, and then you began with ad hominen attacks. If you have such a problem with the code listing above, feel free to point out the actual problems you feel are there. If you have an opinion, try defending it with actual arguments.

                            E) In regards to <stdio.h>, regardless of whether it is depricated or not, it is still in wide use. Not only is it in wide use, but C++, by design, retains all of C in its specification. <stdio.h> is not depricated in C and as such will not be going away soon nor is it bad practice within C to use it. I might add I only added it to quickly output an example. The class itself has nothing to do with it and as such it is meaningless as to whether it is depricated or not.
                            Last edited by fauxanadu; Jul 8 '08, 08:00 PM. Reason: Added E

                            Comment

                            • Laharl
                              Recognized Expert Contributor
                              • Sep 2007
                              • 849

                              #15
                              The deprecated part is using it as <stdio.h> rather than <cstdio>. That's been deprecated for about 10 years now. However, all this is more than a little off topic for this thread. How about we all just calm down a little, mmkay? I'll need you guys to come in on Saturday too, mmkay. </lumbergh>

                              Comment

                              Working...