Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't these two C programs produce the same result?

I wrote this program first, it recursively calculates pi and stops when the error value is small enough.

 #include <stdio.h>`
 #include <stdlib.h>
 #include <math.h>

int threads=1;
double error=0.000001;
double func(double);


struct args{
         double l;
         double r;
         double fl; 
         double fr; 
         double area;};

double quad(struct args*);

int main(int argc, char *argv[]) {

    struct args* res = (struct args*)malloc(sizeof(struct args));
    res->l=0;
    res->r=1;
    res->fl=1;
    res->fr=0;
    res->area=0;

    double ans=quad(res);
    free(res);

    ans=ans*4;

    printf("pi=%f\n",ans);


}


double func(double x){
        x=(1-(x*x));
        x=sqrt(x);
        return x;
    }


double quad(struct args* arg){
    double m=(arg->l+arg->r)/2;
    double fm=func(m);
    double larea=(arg->fl+fm)*(m-arg->l)/2;
    double rarea = (fm+arg->fr)*(arg->r-m)/2;

    struct args* arg1 = (struct args*)malloc(sizeof(struct args));
    arg1->l=arg->l;
    arg1->r=m;
    arg1->fl=arg->fl;
    arg1->fr=fm;
    arg1->area=larea;

    struct args* arg2 = (struct args*)malloc(sizeof(struct args));
    arg2->l=m;
    arg2->r=arg->r;
    arg2->fl=fm;
    arg2->fr=arg->fl;
    arg2->area=rarea;
    if(fabs((larea+rarea)-arg->area)>error){
        if(threads<=1){
            larea=quad(arg1);
            rarea=quad(arg2);

            free(arg1);
            free(arg2);
        }

    }

    return(larea+rarea);
}

This one works as it should but then I tried to make the quadfunction return a void pointer instead of a double it looked like this.

#include <stdio.h>`
 #include <stdlib.h>
 #include <math.h>

int threads=1;
double error=0.000001;
double func(double);
struct args{
         double l;
         double r;
         double fl; 
         double fr; 
         double area;};

void* quad(struct args*);

int main(int argc, char *argv[]) {

        struct args* res = (struct args*)malloc(sizeof(struct args));
        res->l=0;
        res->r=1;
        res->fl=1;
        res->fr=0;
        res->area=0;
        void* ans=quad(res);

        double val=*(double*)ans;
        val=val*4;

        free(res);


         printf("pi=%f\n",val);
   }

 double func(double x){
    x=(1-(x*x));
    x=sqrt(x);
    return x;
    }

void* quad(struct args* arg){
    double m=(arg->l+arg->r)/2;
    double fm=func(m);
    double larea=(arg->fl+fm)*(m-arg->l)/2;
    double rarea = (fm+arg->fr)*(arg->r-m)/2;

    struct args* arg1 = (struct args*)malloc(sizeof(struct args));
    arg1->l=arg->l;
    arg1->r=m;
    arg1->fl=arg->fl;
    arg1->fr=fm;
    arg1->area=larea;

    struct args* arg2 = (struct args*)malloc(sizeof(struct args));
    arg2->l=m;
    arg2->r=arg->r;
    arg2->fl=fm;
    arg2->fr=arg->fl;
    arg2->area=rarea;
    if(fabs((larea+rarea)-arg->area)>error){
        if(threads<=1){
            void* p1=quad(arg1);
            void* p2=quad(arg2);
            larea=*((double*)p1);
            rarea=*((double*)p2);

            free(arg1);
            free(arg2);
        }
    }


    double ret= (larea+rarea);
    void*poin=&ret;

    return poin;
}

This program while it compiles just gives me a completely different result, 0.042298 rather than 3.14159. I'm pretty new to C and using pointer so I'm sure I messed something up with the conversions but I can't for the life of me figure out where.

Any help figuring out why these two programs produce different results would be appreciated. Thanks.

like image 368
John Slaine Avatar asked Nov 18 '25 03:11

John Slaine


2 Answers

You are returning a pointer to ret. A variable that is local to quad(). By the time you look at it it has been replaced.

Also dereferencing an invalid pointer is undefined behaviour. Which means your compiler is free to do whatever, like format your hard drive or start WW3.

like image 173
kamikaze Avatar answered Nov 20 '25 16:11

kamikaze


Your non-working function returns a pointer to a local variable which will go out of scope and life when the function ends.

double ret = (larea+rarea);
void *poin = &ret;
return poin;

Whereas the working version returns the actual double value.

Why ever did you change the function to return a void* pointer anyway?

like image 28
Weather Vane Avatar answered Nov 20 '25 18:11

Weather Vane



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!