3

So I'm currently reading and learning a code from the internet (related to artificial neural network) and I found a part of the code that I don't understand why it works.

double* inputNeurons;
double* hiddenNeurons;
double* outputNeurons;

This is how it was declared. Then in this next code, it was changed and used as an array?

inputNeurons = new( double[in + 1] );
for ( int i=0; i < in; i++ ) inputNeurons[i] = 0;

inputNeurons[in] = -1; // 'in' is declared in the function as an int

So, I want to understand why and how it works. Did it become an array of "doubles"? If so, in what way can I also use this? Can this be used for struct or even class?

Jeremy
  • 43
  • 5
  • 1
    The code looks like it has a bug in it. But syntactically, pointers can be indexed just like arrays. This can be quite handy if they point to an element in an array. – juanchopanza Sep 05 '15 at 15:33
  • The code works, as I compiled it and tested what it does. – Jeremy Sep 05 '15 at 15:37
  • See [this related question](http://stackoverflow.com/questions/4622461/difference-between-pointer-index-and-pointer) – juanchopanza Sep 05 '15 at 15:37
  • Yes, you are right. I misread the position of the parentheses in `inputNeurons = new( double[in + 1] );` – juanchopanza Sep 05 '15 at 15:40
  • I hope the allocated memory was destroyed later on in the code (delete [ ]) – Pedro Isaaco Sep 05 '15 at 16:02
  • It is, there's a constructor and destructor – Jeremy Sep 05 '15 at 16:22
  • `for( int i = 0; i < in; i ++ ) inputNeurons[i] = 0;` would be better written as `memset(inputNeurons, 0, in);` – Braden Best Aug 19 '16 at 04:26
  • Also, if `-1` is a meant to be a sentinel value, it would be better to store the *length* of the array instead. Either as the first element (size preceding data), or by combining the array and its length in a structure/class. I think that's where vectors come in. – Braden Best Aug 19 '16 at 04:34

3 Answers3

5

Every array can be treated as a pointer. But that does not mean every pointer is an array. Do not mix this up!

Assuming we have an array int test[..], the variable name also represents the address where the array is stored in the memory. So you could write

int * p = test;

At that moment my pointer p "becomes" an array, where "becomes" means 'points to an array'. Your example is similar - the only difference is that the memory is allocated dynamically (heap) and not on the stack (as in my example).

So how are the elements accessed? Let's say, we want to get the first element (index 0). We could say

int i = test[0];

or we could say

int i = *p;

Now we want to get the element at index 1:

int i = test[1];

Or - by using pointer arithmetics we could write

int i = *(p + 1);
Pedro Isaaco
  • 404
  • 3
  • 10
2

In C++ (and C) pointers support indexing operator [] which basically adjusts the value of the pointer by the amount specified times the size of the type pointed.

So basically

inputNeurons[5] = 0;

is equivalent to

*(inputNeurons+5) = 0

Now this doesn't give you any guarantee about the fact that inputNeurons points to an address which is correctly allocated to store at least 6 double values but syntactically it is correct and well defined.

You are just adjusting an address to point to the i-th element of a given type starting from the specified address.

This means that

double x;
double* px = &x;
px[5] = 0;

Is syntactically correct although it is wrong, since px+5 is an address which points to memory which has not been reserved correctly to hold that value.

Jack
  • 131,802
  • 30
  • 241
  • 343
  • 1
    I'd say your example is equivalent to `inputNeurons+5`, without that sizeof part – Piotr Skotnicki Sep 05 '15 at 15:38
  • Can this be used for structs and class too? Like myStruct* neurons; neurons = new(myStruct[5]); and have 5 myStructs that can be accessed with [0]...[4]? – Jeremy Sep 05 '15 at 15:43
  • Yes, correct syntax is `myStruct* neurons = new myStruct[5];` but mind that you are working in C++ so a `vector` could be a better solution. Don't foget that with `new` you need `delete` and if you are allocating an array you __must__ use `delete [] neurons` since the compiler can't figure out that the pointed data is indeed an array and not just a single value. – Jack Sep 05 '15 at 15:44
  • @Jeremy Yes, it works for all default constructable types. But the parentheses make it look confusing. The usual syntax is `T* a = new T[N];` – juanchopanza Sep 05 '15 at 15:45
  • vector? I'll try to look it up, thanks for the suggestion man – Jeremy Sep 05 '15 at 15:51
  • Using a `std::vector` will help you since it automatically grows as need and it manages memory automatically (so you don't need `new` and `delete` at all). – Jack Sep 05 '15 at 15:52
0

The pointer of type double (double* inputNeurons;) just gets assigned to point to the beginning of an dynamically allocated array (new( double[in + 1])) of the same type. It does not become an array.

You can do this with any other pointer and regular array of the same type. As a matter of fact an array is a pointer to specific address (to its beginning, i.e. to the element with index: 0).

When you increment the pointer by + 1, that one means 1 * type_size (i.e 1 * size_of_double)

In your case: inputNeurons points to the address of the first element of the array. If you dereference it: *inputNeurons, you will get the value stored at that address (if inputNeurons was an array, it would be equivalent to: inputNeurons[0] ).
To access the next element just increment by one (*inputNeurons + 1).

Ziezi
  • 6,375
  • 3
  • 39
  • 49