Question about avoid dereferencing NULL


#1

With this function:

[code]void cartesianToPolar(float x, float y, double *rPtr, double *thetaPtr)
{
// store the radius in the supplied address
// is rPtr non-NULL?
if (rPtr) {
*rPtr = sqrt(x * x + y * y);
}

// is thetaPtr NULL?
if (!thetaPtr) {
    return;
}[/code]

and then the function being called like this:

shouldn’t it return back and not perform the function? (I left out the rest of the function that does the conversion). Even when passing NULL it still completes it and return back 0.00.


#2

I’m not sure I understand the question.

cartesianToPolar() would calculate the radius and put it in the correct location. And then, because the thetaPtr was NULL, would skip the rest of the function.

The function doesn’t return anything (its return type is void). All the data is passed by reference.


#3

Sorry suppose I should have proofread my question before posting…

since I am passing NULL to the function and it is checking to see if what was passed was NULL and if so return from performing the function, shouldn’t that be what it does? Instead it continues through executing the function.


#4

Yes, that is what should happen. What evidence do you have that the rest of cartesianToPolar() is being executed?


#5

Here is the whole program:

[code]#include <stdio.h>
#include <math.h>

void cartesianToPolar(float x, float y, double *rPtr, double *thetaPtr);

void cartesianToPolar(float x, float y, double *rPtr, double *thetaPtr)
{
// store the radius in the supplied address
// is rPtr non-NULL?
if (rPtr) {
*rPtr = sqrt(x * x + y * y);
}

// is thetaPtr NULL?
if (!thetaPtr) {
    return;
}

// cacculate theta
float theta;
if (x == 0.0) {
    if (y == 0.0) {
        theta = 0.0; // technically considered undefined
    } else if ( y > 0) {
        theta = M_PI_2;
    } else {
        theta = - M_PI_2;
    }
} else {
    theta = atan(y/x);
}

// store theta in the supplied address
*thetaPtr = theta;

}

int main (int argc, const char * argv[])
{
double pi = 3.14;
double integerPart;
double fractionPart;

// pass the address of integerPart as an argument
fractionPart = modf(pi, &integerPart);

// find the value stored in integerPart
printf("integerPart = %.0f, fractionPart = %.2f\n", integerPart, fractionPart);

// pass by referance
double x = 3.0;
double y = 4.0;
double radius;
double angle;

cartesianToPolar(x, y, &radius, NULL);
printf("(%.2f, %.2f) becomes (%.2f radians, %.2f)\n", x, y, radius, angle);

return 0;

}

[/code]


#6

Ahh… I was confused by this one too, but got it figured.

Remember that the code starts at the top and works its way down. If you pass theta as NULL it still completes the radius calculation before it returns out of the cartesianToPolar() function.

Compiled code or not, it still starts at the top and works its way down.


#7

There is something I don’t understand :
I thought the program started with the “main” function, which in turn called the cartesianToPolar function.
So, when you declare the angle and radius variables :
[color=#0000FF]double x = 3.0;
double y = 4.0;
double radius;
double angle;[/color]
radius and angle should be to zero, should they not ?
And the if check :
[color=#0000FF] if (rPtr) { [/color]
should deal with a 0 value ?

I guess I’m still confused with pointers … if someone can help me figure this out, I’ll be grateful !
Thanks
Fred


#8

Imagine that the line says this:

double radius = 0;
The data for radius is stored at a particular address in memory. The value stored there is zero, but the address is not.

Here you are passing not zero, but the non-zero address. So this check:

Is true, because the address is not zero.


#9

[quote=“AaronHillegass”]Imagine that the line says this:

double radius = 0;
The data for radius is stored at a particular address in memory. The value stored there is zero, but the address is not.

Here you are passing not zero, but the non-zero address. So this check:

Is true, because the address is not zero.[/quote]

Ah, OK ! So that means that the address in memory is always filled, unless the variable has not be used, right ?
Thanks Aaron ! I love your book so far !


#10

I would say, “The data is copied to the address rPtr, unless that address is NULL.”


#11

I think that the title Avoid dereferencing NULL is not a good choice. In reality, if you try to dereference NULL you will get a EXC_BAD_ACCESS error.
But, when you declare a function with pointer types as parameters, is implicit that is responsibility of the developer that use the function to pass non-NULL addresses to the pointer types parameters. Normally, you don’t test for NULL before dereferencing the pointer variable inside a function. This behavior is true in various of the Standard C Libraries functions. For example, in math.h , all the following functions throws the EXC_BAD_ACCESS error if the NULL is passed to pointer type parameters: double modf(double, double *), double remquo(double, double, int *), and double frexp (double, int *).