views:

47

answers:

2

I'm using Qt Creator 4.5 with GCC 4.3 and I'm having the following problem that I am not sure is Qt or C++ related: I call a function with a char * as an input parameter. Inside that function I make a dynamic allocation and I assign the address to the char *. The problem is when the function returns it does not point to this address anymore.

bool FPSengine::putData (char CommandByte , int Index)
{
  char *msgByte;
  structSize=putDatagrams(CommandByte, Index, msgByte);
}

int FPSengine::putDatagrams (char CommandByte, int Index, char *msgByte)
{
  int theSize;

  switch ( CommandByte ) {

    case (CHANGE_CONFIGURATION): {
      theSize=sizeof(MsnConfigType);
      msgByte=new char[theSize];

      union MConfigUnion {
        char cByte[sizeof(MsnConfigType)];
        MsnConfigType m;
      };

      MConfigUnion * msnConfig=(MConfigUnion*)msgByte;

      ...Do some assignments. I verify and everything is OK.
    }
  }
  return theSize;
}

When I return the pointer it contains a completely different address than the one assigned in putDatagrams(). Why?
...

Ok thx I understand my mistake(rookie mistake :( ). When sending a pointer as an input parameter to the function you send the address of your data but not the address of your pointer so you cant make the pointer point somewhere else...it is actually a local copy like Index. The only case the data would of been returned succesfully with the use of a char * is by allocating the memory before the function call:

bool FPSengine::putData (char CommandByte , int Index)
{
  char *msgByte;
  msgByte=new char[sizeof(MsnConfigType)];
  structSize=putDatagrams(CommandByte, Index, msgByte);
}

int FPSengine::putDatagrams (char CommandByte, int Index, char *msgByte)
{
  int theSize;

  switch ( CommandByte ) {

    case (CHANGE_CONFIGURATION): {
      theSize=sizeof(MsnConfigType);

      union MConfigUnion {
        char cByte[sizeof(MsnConfigType)];
        MsnConfigType m;
      };

      MConfigUnion * msnConfig=(MConfigUnion*)msgByte;

      ...Do some assignments. I verify and everything is OK.
    }
  }
  return theSize;
}
+2  A: 

Well, yes. Everything in C++ is, by default, passed by value. Parameters in the call putDatagrams(a, b, c) are sent by value - you wouldn't expect assigning to index in the code to change the value of b at the call site. Your msgByte=new char[theSize]; is just assigning to the local variable msgByte, overwriting the value passed in.

If you want to change a passed parameter such that the call site variable changes, you'll need to either pass by reference, or (in this case) pass a "pointer to a pointer` (and deference away the first pointer, assigning to the actual pointer).

Adam Wright
is this only true in C++ or in C as well
yan bellavance
In C as well. Though C has no references, so you can't pass by reference - only pointers to pointers.
Adam Wright
+3  A: 

There are two ways. The pass-by-value way (C style):

int FPSengine::putDatagrams (char CommandByte, int Index, char **msgByte)

Note the second * for msgByte. Then inside of putDatagrams(), do:

*msgByte = new char[theSize];

In fact, anywhere in that function where you currently have msgByte, use *msgByte. When calling putDatagrams(), do:

structSize=putDatagrams(CommandByte, Index, &msgByte);

And the second way, since you're in C++, you could use pass-by-reference. Just change the signature of putDatagrams() to:

int FPSengine::putDatagrams (char CommandByte, int Index, char * &msgByte)

And you should be good. In this case, you shouldn't need to modify the caller or anything inside of your putDatagrams() routine.

Carl Norum