0

I will try to be as explicit as I can.

I have an exercise to solve, I've searched a lot on the web but could not find what my issue is.

Because this is an 'as is' Exercise I cannot modify float* to float[], I must use the values given and the function signature given. All I can work with is the contains of setWeight function.

Consider the following:

class Train
{
    protected:
    float* weight;

    public:
    setWeight(float* weight)
    {
        this->weight = weight;
    }
}

Then in main I call the following:

main()
{
    float weights[] = { 30.5f, 20.0f, 12.7f, 15.88f };
    train.setWeight(weights);
}

When I look in debug mode only the first value gets passed. Can someone help me out?

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
  • 7
    The debugger probably can't work out that `weight` points to an array. A pointer to a `float` is basically indistinguishable from a pointer to the first element of an array of `float`. – François Andrieux May 20 '21 at 20:07
  • 3
    Yet another question: How does your `class Train` know how many values the array has which is stored in `float* weight;`? (Actually, it doesn't if you don't pass and remember the size as well, or even better, use a C++ std container instead.) – Scheff's Cat May 20 '21 at 20:09
  • The main thing you are missing here is that in C-ish languages, array notation and pointer notation are interchangeable, and array names and pointers are (with some exceptions) interchangeable. So you can do `[0]` to dereference a pointer, and `*` to get the 0th element of an array. – T.E.D. May 20 '21 at 20:28
  • 1
    Thank you for using your debugger, by the way. You're saving yourself, and by extension all of us, a lot of time. – user4581301 May 20 '21 at 21:38

4 Answers4

5

The program hasn't done anything wrong, but you are looking at it wrong.

In the debugger instead of reading train.weight and letting the debugger follow the pointer, try reading train.weight[0], train.weight[1], and train.weight[3]

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • 2
    With Visual Studio you can tell the debugger a pointer points to an array, and how many elements come after it. If you have a pointer `ptr` which points to an array of 5 elements you can put a watch on `ptr,5` and the debugger will show the 5 values as-if `ptr` was an array. – François Andrieux May 20 '21 at 20:23
  • @FrançoisAndrieux: Yes, most debuggers support something like that, but it is pretty inconsistent and not worth learning the syntax to merely prove that the object can find all of the values. – Ben Voigt May 20 '21 at 20:25
-1

If you cannot modify the signature of setWeight, you can provide the data as a dynamically allocated array.

main()
{
    Train train;
    float* weights = new float[4]{ 30.5f, 20.0f, 12.7f, 15.88f };
    train.setWeight(weights);

    //...
    delete[] weights;
}

Be aware you must at some point delete[] weights, and the moment you do, train will no longer contain valid values.

In the future, if you write a class similar to this, use RAII: Allocate with new in the constructor, and deallocate with delete in the destructor.

Camwin
  • 413
  • 3
  • 10
  • I recommend explaining this one a bit better. Why are you doing this? If the asker doesn't know why you did something, all they can do is copy your code and join the ranks of the [cargo cult programmers](https://en.wikipedia.org/wiki/Cargo_cult_programming). Specifically, focus on how this allows the debugger to see additional values in the array inside the called function. – user4581301 May 20 '21 at 21:33
  • It's hard to know from the given code what the lifetime of the weight member is or how it will be used by another method. – Camwin May 20 '21 at 23:22
  • In the context of the question, the lifetime is guaranteed to exceed the function call so there is no need for `new` at all. The question was "Why is only the first value passed into the function?" and the answer is "The whole array was passed in, but it decayed to a pointer so the debugger only knows for sure about the first value." – user4581301 May 20 '21 at 23:28
-2

BACKGROUND: A pointer is a "special" type that stores a memory address. In this case, is a float value.

The thing is that an array is just syntactical sugar for handling pointers, since the name of an array is a pointer to the first element. If it's more general like a matrix, the compiler will run some fancy calculations to get it done. If you use a debugger, you will probably end up with that kind of situation since there is no way for the debugger to know that that pointer corresponds to a single value or the start of an array, a matrix, etc...

For example, this notation:

arr[1]

is translated as:

*(arr + 1)

PD: A cool trick you can retrieve from this, is that since the sum is commutative, you can transform the last expression in this:

*(arr + 1)
*(1 + arr)
1[arr]

And still works.

Dharman
  • 30,962
  • 25
  • 85
  • 135
Isaac Vega
  • 300
  • 3
  • 6
  • 4
    An array is not a pointer. Pointers and arrays are different types. It can be easy to think of them as the same thing, but they are completely different. Arrays like to decay to pointers, and array type function arguments actually *are* pointers (they aren't arrays), so the confusion is understandable. Pointers to arrays exist, references to arrays exist, arrays can have a different size than a pointer. There are many other subtle differences. See [Arrays are Pointers?](https://stackoverflow.com/questions/3959705/arrays-are-pointers). – François Andrieux May 20 '21 at 20:21
-2

It's because you cannot this way, and it's really dangerous.

Hard array have a fixe space in memory, and is meant to be free when the variable go out of the scope.your pointer (float *) is just an adress to a memory space, you make it point to your hard memory space that will be free when you get out of the function, you will crash when you will try to use your variable.

    void setWeight(float* weight)
{
  float* Weight;
  Weight = weight;

  for (int i = 0; i < 4; ++i)
  {
    std::cout << *Weight << std::endl;
    ++Weight;
  }
}

int main()
{
  float weights[] = { 30.5f, 20.0f, 12.7f, 15.88f };
  setWeight(weights);
}

As you can see, i can see each hard float because i already know the size of the hard float array. When i do ++Weight i'm incrementing the pointer adress to go to the next value. (++Weight, is the same as Weight = Weight + 1)

BUT, it's not a copy, you have just a pointer to a hard space that will be free, and i need to know the size of the float[] passed in parameter

if we were in C i would tell you to malloc some space and copy one to the other, but, in c++ if you cna change the type of variable in your class, i will suggest a vector of float : std::vector<float> weight;

Samael
  • 61
  • 1
  • 9