Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 Arrays and Mutability
Index -> Programming, C++ -> C++ Help
Goto page 1, 2  Next
View previous topic Printable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
apython1992




PostPosted: Mon Jul 04, 2011 3:52 pm   Post subject: Arrays and Mutability

Hey guys, I'm back with another pointer question for my raytracer. I've encountered a situation where I declare a fixed array as a local variable in a function, and pass it into another function where I expect it to be modified. I've stepped through my code to make sure that the value actually *is* getting modified, but when control is returned to the original function, the value is the same. I feel like this may have something to do with a subtle difference between arrays and pointers, but I haven't found anything online to suggest that there is a problem with this. For reference, here is a dummy example of what I'm talking about:

c++:

int main()
{
    double my_array[3];
    some_function(my_array);
    // after function call, my_array hasn't changed as it should have in some_function
    return 0;
}

void some_function(double *array)
{
    // stuff that modifies array
}


While I *do* think that this is because I'm erroneously treating an array as a pointer, I would like someone who knows a thing or two about C or C++ to verify this/tell me otherwise. Thanks!
Sponsor
Sponsor
Sponsor
sponsor
crossley7




PostPosted: Mon Jul 04, 2011 4:07 pm   Post subject: RE:Arrays and Mutability

try

c++:

void some_function (double &array)
{

}


I believe you just have reference and dereference operators backwards. Check this page out to get straightened out. As it is I get confused by these regularly and avoid them if i can

http://www.cplusplus.com/doc/tutorial/pointers/
Insectoid




PostPosted: Mon Jul 04, 2011 5:29 pm   Post subject: RE:Arrays and Mutability

Yay pointers! I still get confused sometimes too. Remember fellas, there are 3 values associated with pointers! Their own location, the location they store and the data at the location they store.

Treating a pointer like a regular primitive type (ie no special symbols) returns the location the pointer is storing.

Any time you use an asterix, you're working with the data at the location being stored.

Any time you use an ampersand, you're working with the pointer's own location. Note this operator returns a pointer to self for all primitive types (and probably some/most/all complex types).

But you're making a raytracer, so I guess you're already aware of and practised in pointer use. I'm just writing this to prove to myself that I still know it. Also, how did I ever accomplish anything at all in Turing with no pointers (I know Turing supports pointers, but I never used them)?
apython1992




PostPosted: Mon Jul 04, 2011 5:39 pm   Post subject: Re: RE:Arrays and Mutability

crossley7 @ Mon Jul 04, 2011 4:07 pm wrote:
try

c++:

void some_function (double &array)
{

}


I believe you just have reference and dereference operators backwards. Check this page out to get straightened out. As it is I get confused by these regularly and avoid them if i can

http://www.cplusplus.com/doc/tutorial/pointers/


Actually what I'm doing here with the asterisk isn't a dereference operator - this seems to be a common source of confusion amongst C/C++ programmers. Take a look at the following:
c++:
int num = 3;
int *p = #
int other_num = *p;


In this example, the first asterisk is used to declare a pointer to an int, whereas the second asterisk is used to dereference 'p" and obtain the value at the location it points to. Here, num = 3, p would be something like 0x2afc38, and other_num = 3.

All clear?

@Insectoid - this is my first time doing anything remotely serious in C++, so you can well imagine I've had my share of frustrations up to this point Smile Not just with pointers, but with the various uses of the const keyword mingled in with class inheritance...it's been fun to say the least.
Tony




PostPosted: Mon Jul 04, 2011 5:52 pm   Post subject: RE:Arrays and Mutability

It gets even more fun when you have const pointers. One of the interpretations might be "pointer to a constant address (can't change the value of the pointer), but data at that address is mutable". Yay C++ Laughing
Latest from compsci.ca/blog: Tony's programming blog. DWITE - a programming contest.
Insectoid




PostPosted: Mon Jul 04, 2011 6:22 pm   Post subject: RE:Arrays and Mutability

Isn't that exactly what happens when you declare an array of characters in the following manner?
code:
char foo[5];
.

As far as I can tell, this is identical to the following:
code:
const char *foo = (char*) malloc (5*sizeof char)
apython1992




PostPosted: Mon Jul 04, 2011 6:44 pm   Post subject: RE:Arrays and Mutability

Only difference is that foo in the second example would reside in memory allocated from the heap as opposed to the stack or global memory.

@Tony - I think I've seen examples of the const keyword placed after every other identifier/name in a class method:
c++:
const char* const blah(const *value) const;

Which kinda blows my mind. I see the value in it though in terms of code-safety - things will get caught at compile time instead of tossing you a deadly little segfault your way at runtime.

Back to my original post, does anyone have any ideas?
crossley7




PostPosted: Mon Jul 04, 2011 7:31 pm   Post subject: RE:Arrays and Mutability

I guess I learn something new in c++ every time I open it. That is part of why I almost never use pointers. I have no idea how to use them.

My only experience with them is mostly from a few tutorials and SDL surface declarations. Wish I could actually understand how they work, think I've looked at and tried to learn pointers a bunch of times
Sponsor
Sponsor
Sponsor
sponsor
Tony




PostPosted: Mon Jul 04, 2011 7:38 pm   Post subject: RE:Arrays and Mutability

@Insectoid -- not quite, there are some C++ internals magics (aren't there always?)
Quote:


tony$ cat test.cpp
#include <iostream>
using namespace std;
int main()
{
char foo1[5];
const char *foo2 = (char*) malloc (5*sizeof(char));
cout << sizeof(foo1) << endl;
cout << sizeof(foo2) << endl;
return 0;
}
tony$ g++ test.cpp
tony$ ./a.out
5
8


@apython1992 -- can you extend your example such that you actually try to modify the values?
Latest from compsci.ca/blog: Tony's programming blog. DWITE - a programming contest.
apython1992




PostPosted: Mon Jul 04, 2011 8:06 pm   Post subject: RE:Arrays and Mutability

It will probably be easier if I post the two functions in question in case there is something else I am overlooking. First, here is the first function I talked about (it does nowhere near what it is supposed to yet). It declares an array called "intersect" of size 3, and then it gets passed to the object.get_intersect() method. Basically, if there is no intersection point, I just set intersect to 0 (null pointer), but that doesn't appear to ever happen back in raytrace() (like I said, I've stepped through my code to see if it actually does get set to 0 in get_intersect()).

c++:

void raytrace(Ray *ray)
{
    double intersect[3];
    double *min_intersect;
    double curr_mag = 0;
    double min_mag = 0;

    // See if ray hits any objects, and get the closest intersection point
    for (unsigned int i = 0; i < objects.size(); i++)
    {
        objects[i]->get_intersect(ray, intersect);

        if (intersect == 0) continue;

        curr_mag = sqr_mag(intersect);

        if (i == 0)
        {
            min_mag = sqr_mag(intersect);   // Origin is (0, 0, 0) so we don't need vector subtraction here
            min_intersect = intersect;
        }
        else if (curr_mag < min_mag)
        {
            min_mag = curr_mag;
            min_intersect = intersect;
        }
    }

    if (min_intersect != 0)
    {
       cout << min_intersect[0] << ' ' << min_intersect[1] << ' ' << min_intersect[2] << endl;
    }
    else cout << "No intersect." << endl;
}


And the get_intersect() method (spheres):
c++:

void Sphere::get_intersect(const Ray *ray, double *intersect) const
{
    double ray_to_center[3];
    const int *ray_origin = ray->get_origin();
    double *ray_direction = ray->get_direction();

    // Obtain vector from ray origin to center of sphere
    for (int i = 0; i <= 2; i++)
        ray_to_center[i] = m_origin[i] - ray_origin[i];

    // Dot the ray with this vector to get the closest approach
    double tc = dot(ray_direction, ray_to_center);

    if (tc <= 0)
    {
        intersect = 0;
        return;             // Don't want backwards intersections
    }

    double center_to_ray[3];

    for (int i = 0; i <= 2; i++)
    {
        intersect[i] = tc * ray_direction[i] + ray_origin[i];
        center_to_ray[i] = intersect[i] - m_origin[i];
    }

    // Take magnitude of line drawn from calculated point to center
    // of sphere; if greater than radius, no intersect, if equal, return
    // calculated point, else carry out final calculation
    double mag = sqr_mag(center_to_ray);

    if (mag <= EPSILON)
    {
        tc -= m_radius;

        for (int i = 0; i <= 2; i++)
            intersect[i] = tc * ray_direction[i] + ray_origin[i];
    }
    else if (mag > m_radius)
    {
        intersect = 0;
    }
    else
    {
        // Use Pythagorean Theorem to calculate closest point based on right triangle
        double tf = tc - sqrt(m_radius - mag);

        for (int i = 0; i <= 2; i++)
            intersect[i] = tf * ray_direction[i] + ray_origin[i];
    }
}
DemonWasp




PostPosted: Tue Jul 05, 2011 8:04 am   Post subject: RE:Arrays and Mutability

I'm pretty sure your array is getting passed by value, which means copying. If you print out the value of "&intersect" just before the call to get_intersect() and just inside that function, you'll find that they're different (if I'm correct).

What you probably want is for your method signature to look like:

c++:

void Sphere::get_intersect(const Ray *ray, double ** intersect) const


Note the two stars -- it's a pointer to an array, so one star for pointer, one for array.

Then your method call looks like:
c++:

objects[i]->get_intersect(ray, &intersect);


Note the & operator being used to get the address of intersect so you can pass a pointer by value.

Now, I'm not a C++ expert and I haven't tried this right this moment, so I could be totally wrong. You should probably try this on your trivial example first. There may also be a "neater" way of doing it, but I wouldn't know.
apython1992




PostPosted: Tue Jul 05, 2011 8:45 am   Post subject: Re: RE:Arrays and Mutability

DemonWasp @ Tue Jul 05, 2011 8:04 am wrote:
I'm pretty sure your array is getting passed by value, which means copying. If you print out the value of "&intersect" just before the call to get_intersect() and just inside that function, you'll find that they're different (if I'm correct).

Passing an array into a function will pass a pointer to its first element. I have verified that my array *is* getting passed by reference (a pointer to the first element of the array is passed, by value). I think I have found my problem, though: In get_intersect, if there is no intersection point I am trying to change the pointer's address in memory (pointing to NULL), which I believe is strictly forbidden with arrays, because they are essentially constant pointers. I'm finding myself getting thoroughly surprised by the behaviour of g++ - it sure isn't picking up a lot of these mis-uses (though to be fair, I'm only compiling using the default settings in Code::Blocks, so I should probably add some flags to help me catch some of this stuff).

All this being said - is there an easy way to get array-like behaviour on the stack without having to treat is as a const pointer? If not, I can find another mechanism for handling non-intersections, but I may as well learn something. Smile

Appreciate the help guys.
apython1992




PostPosted: Tue Jul 05, 2011 9:05 am   Post subject: Re: RE:Arrays and Mutability

Insectoid @ Mon Jul 04, 2011 6:22 pm wrote:
Isn't that exactly what happens when you declare an array of characters in the following manner?
code:
char foo[5];
.

As far as I can tell, this is identical to the following:
code:
const char *foo = (char*) malloc (5*sizeof char)


Also I think this is a pointer which points to values that are const. Instead, we'd want a constant pointer with mutable values. It would have to be
code:
char * const foo = (char *) malloc(5 * sizeof(char))


I think that syntactically it should be the other way around. Makes more sense to me.
DemonWasp




PostPosted: Tue Jul 05, 2011 9:37 am   Post subject: RE:Arrays and Mutability

Part of the value of stack allocation is the assurance that the value is non-nullable (see RAII). You should probably just return a boolean indicating intersection or non-intersection.
apython1992




PostPosted: Tue Jul 05, 2011 9:43 am   Post subject: RE:Arrays and Mutability

I do need the actual point of intersection though (because it will be the origin for subsequent rays). I kept everything stack-based and just changed it to set the z co-ordinate of the intersection to -1 if it misses (this would ever happen with the way my raytracer is set up. A bit of a hackish solution, but it'll work).
Display posts from previous:   
   Index -> Programming, C++ -> C++ Help
View previous topic Tell A FriendPrintable versionDownload TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 2  [ 21 Posts ]
Goto page 1, 2  Next
Jump to:   


Style:  
Search: