# Quick C++ problem

1. Dec 13, 2005

### Zurtex

I'm just finishing off my C++ project and I decided when looking at two functions that they would be far more efficent as one function (because they are always used together and as it was it repeats the same code twice).

Now I wanted my output as an array so I could called on the two needed numbers.

So my test code went something like this:

CTenK split_power_two(CTenK number);

CTenK split_power_two(CTenK number)
{
}

Which didn't work at all of course and only returned Two. I've also tried thinks like:

CTenK[2] split_power_two(CTenK number);

CTenK[2] split_power_two(CTenK number)
{
}

And I get some horrible errors for that.

(Note CTenK us just a class we made up and are using)

Any help would be fantastic.

2. Dec 13, 2005

### NateTG

If you want to return the array, you need to use
When you put the []'s at the end, it dereferences them.

In C, (and I assume C++) arrays and pointers are very similar. Effectively,
and
are the same thing, if that makes any sense at all.

P.S. C is also zero-based, so you're doing something weird unless there's a value assigned to Answer[0].

3. Dec 13, 2005

### Staff: Mentor

NateTG is correct. Also, you will have to change your return type from CTenK to CTenK* in order to use the return value as an array in your calling function. Try:

CTenK* split_power_two(CTenK number)
{
}

-Dale

4. Dec 13, 2005

### neurocomp2003

simpler way to think about is to
type define CTenK*

"typedef CTenK* CTenKArray" which may clarify the confusion.
or i'm pretty sure you could do
"typedef CTenK[2] CTenKArray2D"

remember an array should be understood as a ptr to the first element of the array

also NateTG
and
is that correct? i thought it would be *(Answer+1)
------------

5. Dec 13, 2005

### Staff: Mentor

I like the typedef, it does make it more readable and convenient. Particularly for newer programmers who may not be comfortable with arrays/pointers.

NateTG is correct here. The "X[n]" operator is just shorthand for the "*(X+n)" syntax. The confusion is probably because for an array of length 2 both "Answer[2]" and "*(Answer+2)" would be out of bounds and would typically lead to nasty run-time errors.

-Dale

6. Dec 13, 2005

### Zurtex

Thanks, but can't say I understood much of that sorry, but I got the general jist and this code produced no compile errors:

CTenK* split_power_two(CTenK number)
{
}

However I am now stumped how to actually use it, certainly the code:

main ()
{
CTenK dummy=One;
cout << split_power_two(dummy)[1] << "\n";
system("Pause");
}

Just crashes.

7. Dec 13, 2005

### neurocomp2003

DaleSpam: i was under the impression that an array works as

Zurtex:
"CTenK *Answer[1]" defines a pointer to an array of one element.
...exactly what are you trying to do? if you don't mind me asking...
anyways..
line 1: CTenK* split_power_two(CTenK number)
is this correct-> You are inputing 1 TenK in and returning an array of TenK?

line2: should either read: CTenK* ans; or CTenK ans[2];...
the first is an undefined size, that points to the first element.
If you choose to use this method you will need to further "create" or allocate memory for a desired size.
[A] ans=new CTenK[2];
ans=malloc(2*sizeof(CTenk)); //may be wrong syntax haven't used malloc in along while..

The 2nd declaration method is probablly easier.
CTenK ans[2]; //defining a CTenK array of size 2

line 3...*answer[0]=One; what are you tryign to acheive here?
if you're just trying to insert One into element 1(0 idx) you leave off the star*. To access an element using the array-style operator [] is simply
varname[]. IF you choose to use the star you would need to do what was given in one of the above posts: *(answer+#).
what this means is your moving your pointer along "#" of CTenK size memory blocks away from the first...and then getting the element by dereferencing using *. Its easier to understand with the operator [].

so "ans[#]=value;"

line 5: if i'm correct you are only returning the first element.
because *answer is the first element...BUT to return the whole array
------------------
NOTE: everytime you do varname[#] you are accessing the element at # index, if you've allocated that many memory blocks, either through "new", "malloc" or using "Type varname[#];"

NOTE: everytime you do *(answer+#) you are accessing #
# number of CTenK sized memory blocks away from the first.

NOTE: if you wanna work with the whole array you just use the varname without any other symbols...so to return the whole array "return varname"

Hope thats not confusing.

8. Dec 13, 2005

### neurocomp2003

oh yeah so your code would look something like
CTenK* split_power_two(CTenK number)
{
}
NOTE:you may need //*(answer+1*sizeof(CTenK)). my compiler was flaky with this.

main ()
{
CTenK dummy=One;
cout << split_power_two(dummy)[1] << "\n";
system("Pause");
}
//not sure if you can apply [] to the function like that but if it works i learned something new....
try CTenK* array; array= split_power_two(dummy) and
cout << array[1]; if your way doesn't work.

also printf/cout is your friend if your not sure how to use the debugger or too lazy to learn like i am ...printf every step where you think your code is going wrong.

9. Dec 13, 2005

### Zurtex

o.k, nevermind, this is FAR more complicated than I expected it to be.

All I wanted was a function where I put a number in and get an array out. Namely so I can put a number b in and get s and t out, where:

$$b = 2^st + 1$$

The code I've written to work out t, repeats the code to work out s, as I always need both I wanted a code which did them both together.

My course doesn't go in to too much detail about C++ and I've never really liked this whole pointer thing or ever seen any real use for it.

Although I do appreciate the help greatly and will read over this in more detail some other time.

10. Dec 14, 2005

### tilika123

CTenK split_power_two(CTenK number)
{
}

you are returning Answer[2] you need to give it parameters on each answer example if(FFFF)
return ?
else
return ?
and also if CTenK Answer[2]; is an array of type CTenk then the only elements in that array you should use is 0, and 1 because in c++ the elements in the arrays begin at 0 and the last element is null if you need to use Answer[1] and Answer[2] you need to declar a 3 element array so that Answer[3] will be the null or ending character of that array not answer[2]. why it is returning 2 baffles me perhaps it is not returning properly, or someting in the calling program

11. Dec 14, 2005

### Staff: Mentor

Correct. To declare an array of two doubles you use:

to access the first element you can use either Answer[0] or *(Answer+0) and to access the last element you can use either Answer[1] or *(Answer+1)

If you try to access the last element using either Answer[2] or *(Answer+2) you will get a runtime error.

-Dale

12. Dec 14, 2005

### Staff: Mentor

Sorry that I didn't think about this when I replied the first time, but I just realized why my suggestion won't work. In C/C++ arguments are typically passed by value and memory is reclaimed when a variable goes out of scope. So, if you take my suggestion:

CTenK* split_power_two(CTenK number)
{
//...
}

this is what will happen. The program will enter split_power_two and it will allocate enough memory to hold two CTenK and Answer will be set to the address of that block of memory. At the return statement the address of the memory block will be sent to the calling function, then when control passes to the calling routine the memory will be deallocated. So, in the calling process the result will point to an invalid memory location and you will get the crashes that you saw.

You can return structs, classes, and basic types without any trouble, because those are copied by value and when they are deallocated inside the function the calling program still has the copy of the value. With the array only the pointer to the first element is copied by value and the actual data is deallocated and lost. For this reason you usually see arrays intended for output passed in the argument list as follows:

{
return;
}

You could then use it as follows:

main ()
{
CTenK dummy=One;
system("Pause");
}

Pointers are very useful, particularly in object-oriented-programming where they are pretty much essential in C++ in order to implement polymorphism. But they are very confusing for beginners and, as you have seen, they are easy to mix up even for people with experience.

-Good Luck
Dale

Last edited: Dec 14, 2005
13. Dec 14, 2005

### neurocomp2003

ptrs are just as important in C even more some whne your passing around parameters.

14. Dec 14, 2005

### neurocomp2003

oh yeah isn't this in the wrong homework section
and dale you can create an array and return it because its ptrs isn't it? or atleast microsoft treats it as so.
typedef int int2[2];
typedef int* intP;
int* tp(int)
{
//int ret[2];
int2 ret;
//int* ret= new int[2];
//int* ret=(int*)malloc(2*sizeof(int));
ret[0]=1;
ret[1]=2;
return ret;
}

int main(int argc, char*argv[])
{
int* k=new int[2];
k=tp(3);
printf("%d,%d",k[0],k[1]);

return 0;
}

Last edited: Dec 14, 2005
15. Dec 14, 2005

### Staff: Mentor

Yes, neurocomp, and as you point out the key is to use "new" to dynamically allocate the memory rather than the normal static allocation.

When you allocate the memory statically then it will be deallocated as soon as you leave the scope of the function. Then in the calling scope your returned pointer will point to garbage. With dynamic allocation it won't be deallocated until you specifically call "delete". Until then you can pass it in and out of as many functions as you like.

Personally, if I always needed exactly two values I would make it a struct. E.g. CTenKPair.s and CTenKPair.t for the two numbers in the solution. Then you could return it just fine without worrying about pointers, arrays, dynamic allocation, scope, etc.

-Dale

Last edited: Dec 14, 2005