Paynomindtous
Paynomindtous

Reputation: 71

Declaring a double array in c++ using brackets or asterisk

Having a variable declared like this:

double *variable;

which I think is pretty the same that writing

double variable[];

and then some methods working on it;

how is it possible to obtain the length of the array of double? What I mean is, how do I know in which position lies the last inizialized / accessed / written element of variable ?

Upvotes: 5

Views: 55545

Answers (3)

Andreas DM
Andreas DM

Reputation: 10998

Pointers are not arrays.

The code below is an array of size 4:

double arr[] {1.1, 1.2, 1.3, 1.4};

arr refers to a block of memory for example:

0x22fe20 | 0x22fe28 | 0x22fe30 | 0x22fe38 | 0x22fe40

While the below is pointing to the address of the beginning of arr:

double *p_arr {arr};

how is it possible to obtain the length of the array of double?

To get the size you can take the size of arr and devide it by the size of the first element:

size_t arr_len = (sizeof(arr) / sizeof(*arr));

Then, we know that the last initialized element is arr_len - 1.


Instead of manually finding the size ourselves, it's better and safer to use a std::vector:

std::vector<double> arr {1.1, 1.2, 1.3, 1.4};
std::cout << arr.size();

Upvotes: 1

jpo38
jpo38

Reputation: 21514

The main difference is that:

  • double* variable; is a pointer meant to be dynamically allocated during execution (via new or malloc for instance), or may point to a double object (then, it's not an "array").
  • double variable[]; is an array statically allocated (so it's size is defined and fixed during compilation). Note that double variable[]; is not valid as a declaration. Size of the array must be specified (double variable[20]; for instance).

To answer your question: you cannot determine the number of elements of a double* or double[] variable, unless you saved it somewhere yourself.

For instance, if you want to pass the double* object to a function, you'll need to pass both pointer and size (number of elements). Function proptotype is then ( double* data, size_t size ).

size_t mySize = 20;
double* data = new double[20];
callFunc( data, mySize );
delete [] data; // need to be deleted because dynamically allocated

or:

static const size_t mySize = 20;
double data[mySize];
callFunc( data, mySize );
// no need to be deleted because statically allocated

As commented by other users, prefer a std::vector which encapsulate a double* pointer and it's number of elements (among other attributes):

std::vector<double> data;
data.assign( 20, 0.0 );
callFunc( data );

callfunc can then access data values and know it's size using data.size().

Note: For char*, convention is to end up the string by a special character (\0), so, in this case, you can determine the size of the char array by finding this special character (that's what strlen does). You could do something similar with a double* pointer (like having a NaN to identifiy the last item and then recover the array size), but that would just be a hack and is nor conventional, nor recommended.

Upvotes: 7

Spacemoose
Spacemoose

Reputation: 4016

Let me correct you.

double* foo;

declares a pointer to a double, named foo.

double foo[] = {1.1, 2.2, 3.3};

declares an array of doubles named foo, for which no memory has yet been allocated. Leftover from C++'s C's roots, is the fact that an array can decay to a pointer. So it is possible to do the following:

double foo[] = {1.1, 2.2, 3.3};
double bar* = foo[0];  // bar now points to the first element of foo.

But this is does not mean that foo and bar are the same thing. You can use a pointer to iterate over the contents of a c-array (assuming you know the size), , but there are subtle areas where the difference could trip you up (e.g. below).

You could also do something like:

double *foo;
// call something that allocates memory for an array and assigned the address of the first element to foo.

But in that case you are going to have to keep track of the array size yourself. That's why in C++, if you are using a statically allocated array, you should prefer std::array, and if you are using a dynamically allocated array, you should prefer std::vector, as these classes will handle the details better than you are likely to.

There is a cute way, which I don't recommend you use, but is an illustration of the differnece between double* and double foo[], which Scott Meyers talks about in "Effective Modern C++":

template <typename T, std::size_t N>
constexpr std::size_t arraySize(T (&)[N]) noexcept
{
    return N;
}

double foo[] = {1.1, 2.2, 3.3};
constexpr int array_size = arraySize(foo);

Will create a c-array with 3 doubles, and initialize the const_expr (it could be a variable, i used const_expr to make it explicit that this is deduced at compile time) array_size to the size of your array.

But avoid all that if you can and use std::array and std::vector when you can.

Upvotes: 1

Related Questions