448,469 Members | 1,037 Online
Need help? Post your question and get tips & solutions from a community of 448,469 IT Pros & Developers. It's quick & easy.

# A NULL pointer changed after returned?

 P: n/a Hi all, I am new to C and I just started to program for a homework. I included my code down there. It is a fraction "class". I declared the Fraction struct, tried to create some invalid fraction, with denominator zero. A Fraction is created by the newFraction() function, and which in turns call normalize() function to simplify it, but before, the normalize() function will do a check, if the denominator is zero, it will give a error by returning a NULL. Everything works fine for a normal fraction, e.g. 3/4, 5/4, but if I give a "4/0" to the function, it is frustrating. In the normalize function, I am sure it is set to NULL, but back to newFraction, it changed back to 4/0. But if I give a fraction that could be simplified, such as 6/8, it is simpified and returned as 3/4 with no problem. Please help! fix. Fraction.c: #include "Fraction.h" void Case1c() { printFraction(newFraction(0,4));printf("\n"); printFraction(newFraction(4,0));printf("\n"); printFraction(newFraction(0,0));printf("\n"); } int main(void) { printf("Case 1c:\n");Case1c(); return 0; } Fraction.h: #include typedef struct { int sign; int numerator; int denominator; } Fraction; int signOf(int number){ if (number < 0) return -1; else return 1; } int gcd(int num1, int num2){ if (num1 < num2) return gcd(num2, num1); else if ((num1 % num2) == 0) return num2; else return gcd(num2, num1 % num2); } void normalize(Fraction *fr){ int factor; if (fr->denominator == 0) // Invalid function { fr = NULL; // set it to NULL and return printf("Set fr = NULL\n"); if (fr!=NULL) printf("Not null"); else printf("null"); return; } // Take the signs form the numerator and denominator to the sign variable fr->sign *= signOf(fr->numerator); fr->sign *= signOf(fr->denominator); // Absolute the numerator and denominator fr->numerator *= signOf(fr->numerator); fr->denominator *= signOf(fr->denominator); if (fr->numerator == 0) { // If the numerator is 0, simplify it to 0/1 fr->denominator = 1; fr->sign = 1; } else { // Find the gcd of the numerator and denominator, divide them by the gcd factor = gcd(fr->numerator, fr->denominator); fr->numerator /= factor; fr->denominator /= factor; } } Fraction newFraction(int num, int den) { Fraction fr; Fraction *frp; fr.numerator = num; fr.denominator = den; fr.sign = 1; frp = &fr; normalize(frp); if (frp!=NULL) printf("Not null"); else printf("null"); return fr; } void printFraction(Fraction fr) { if (&fr == NULL) printf("Invalid fraction"); if (fr.sign == -1) printf("-"); printf("%i/%i", fr.numerator, fr.denominator); } Nov 14 '05 #1
16 Replies

 P: n/a fix writes: void normalize(Fraction *fr){ int factor; if (fr->denominator == 0) // Invalid function { fr = NULL; // set it to NULL and return printf("Set fr = NULL\n"); if (fr!=NULL) printf("Not null"); else printf("null"); return; This is in the FAQ. 4.8: I have a function which accepts, and is supposed to initialize, a pointer: void f(int *ip) { static int dummy = 5; ip = &dummy; } But when I call it like this: int *ip; f(ip); the pointer in the caller remains unchanged. A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. The called function altered only the passed copy of the pointer. You'll either want to pass the address of the pointer (the function will end up accepting a pointer-to-a-pointer), or have the function return the pointer. See also questions 4.9 and 4.11. -- char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[] ={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x1f6},*p= b,x,i=24;for(;p+=!*p;*p/=4)switch(x=*p&3)case 0:{return 0;for(p--;i--;i--)case 2:{i++;if(1)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}} Nov 14 '05 #2

 P: n/a # void normalize(Fraction *fr){ This copies the Fraction* parameter value into a local variable fr. All changes to fr itself are to this local variable and not propagated back to the caller. It's changes to *fr (or fr->...) that are visible to the caller. You can instead do something like Fraction *normalize(Fraction *fr) { ... return fr; } which propagates changes back to the caller as the function yield. You can then call frp = normalize(frp); if (frp!=NULL) printf("Not null"); else printf("null"); # frp = &fr; # normalize(frp); This passes the address of the structure, not the address of pointer variable to the structure. -- Derk Gwen http://derkgwen.250free.com/html/index.html I hope it feels so good to be right. There's nothing more exhilirating pointing out the shortcomings of others, is there? Nov 14 '05 #3

 P: n/a In 'comp.lang.c', fix wrote: Fraction.c: #include "Fraction.h" First of all, I highly recommend that you change your code organization. It's a very bad idea to have code included in a .h. I suggest a very common approach as follow: /* main.c */ #include "Fraction.h" #include /* macros ================================================== ============ */ /* constants ================================================== ========= */ /* types ================================================== ============= */ /* structures ================================================== ======== */ /* private variables ================================================== = */ /* private functions ================================================== = */ static void Case1c (void) { printFraction (newFraction (0, 4)); printf ("\n"); printFraction (newFraction (4, 0)); printf ("\n"); printFraction (newFraction (0, 0)); printf ("\n"); } /* entry point ================================================== ======= */ int main (void) { printf ("Case 1c:\n"); Case1c (); return 0; } /* public variables ================================================== == */ /* fraction.h */ #ifndef H_FRACTION #define H_FRACTION /* macros ================================================== ============ */ /* constants ================================================== ========= */ /* types ================================================== ============= */ /* structures ================================================== ======== */ typedef struct { int sign; int numerator; int denominator; } Fraction; /* internal public functions =========================================== */ /* entry points ================================================== ====== */ Fraction newFraction (int num, int den); void printFraction (Fraction fr); /* public variables ================================================== == */ #endif /* guard */ /* fraction.c */ #include #include "fraction.h" /* macros ================================================== ============ */ /* constants ================================================== ========= */ /* types ================================================== ============= */ /* structures ================================================== ======== */ /* private variables ================================================== = */ /* private functions ================================================== = */ static int signOf (int number) { if (number < 0) return -1; else return 1; } static int gcd (int num1, int num2) { if (num1 < num2) return gcd (num2, num1); else if ((num1 % num2) == 0) return num2; else return gcd (num2, num1 % num2); } static void normalize (Fraction * fr) { int factor; if (fr->denominator == 0) /* Invalid function */ { fr = NULL; /* set it to NULL and return */ printf ("Set fr = NULL\n"); if (fr != NULL) printf ("Not null"); else printf ("null"); return; } /* Take the signs form the numerator and denominator to the sign variable */ fr->sign *= signOf (fr->numerator); fr->sign *= signOf (fr->denominator); /* Absolute the numerator and denominator */ fr->numerator *= signOf (fr->numerator); fr->denominator *= signOf (fr->denominator); if (fr->numerator == 0) { /* If the numerator is 0, simplify it to 0/1 */ fr->denominator = 1; fr->sign = 1; } else { /* Find the gcd of the numerator and denominator, divide them by the gcd */ factor = gcd (fr->numerator, fr->denominator); fr->numerator /= factor; fr->denominator /= factor; } } /* internal public functions =========================================== */ /* entry points ================================================== ====== */ Fraction newFraction (int num, int den) { Fraction fr; Fraction *frp; fr.numerator = num; fr.denominator = den; fr.sign = 1; frp = &fr; normalize (frp); if (frp != NULL) printf ("Not null"); else printf ("null"); return fr; } void printFraction (Fraction fr) { if (&fr == NULL) printf ("Invalid fraction"); if (fr.sign == -1) printf ("-"); printf ("%i/%i", fr.numerator, fr.denominator); } /* public variables ================================================== == */ Note that I have no changed your code. -- -ed- em**********@noos.fr [remove YOURBRA before answering me] The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/ Nov 14 '05 #4

 P: n/a Derk Gwen wrote: # void normalize(Fraction *fr){ This copies the Fraction* parameter value into a local variable fr. All changes to fr itself are to this local variable and not propagated back to the caller. It's changes to *fr (or fr->...) that are visible to the caller. You can instead do something like Fraction *normalize(Fraction *fr) { ... return fr; } which propagates changes back to the caller as the function yield. You can then call frp = normalize(frp); if (frp!=NULL) printf("Not null"); else printf("null"); # frp = &fr; # normalize(frp); This passes the address of the structure, not the address of pointer variable to the structure. -- Derk Gwen http://derkgwen.250free.com/html/index.html I hope it feels so good to be right. There's nothing more exhilirating pointing out the shortcomings of others, is there? Yup thanks! Nov 14 '05 #5

 P: n/a Ben Pfaff wrote: fix writes:void normalize(Fraction *fr){ int factor; if (fr->denominator == 0) // Invalid function { fr = NULL; // set it to NULL and return printf("Set fr = NULL\n"); if (fr!=NULL) printf("Not null"); else printf("null"); return; This is in the FAQ. 4.8: I have a function which accepts, and is supposed to initialize, a pointer: void f(int *ip) { static int dummy = 5; ip = &dummy; } But when I call it like this: int *ip; f(ip); the pointer in the caller remains unchanged. A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. The called function altered only the passed copy of the pointer. You'll either want to pass the address of the pointer (the function will end up accepting a pointer-to-a-pointer), or have the function return the pointer. See also questions 4.9 and 4.11. Ah...... I got you, so that means if I change the content in the struct, i.e. changing the signs, denom and numerators, the pointer hasn't changed, but if I point it to NULL, I am actually changing the pointer so it reverts to the original value outside the function body. If I am to return a pointer, I am curious that if I return a pointer to a variable created inside the function, will the variable be garbage collected but the pointer still pointing to that? I was learning Java last semester and I have no trouble with pointers....... Nov 14 '05 #6

 P: n/a Is this the order? Does C have any privacy (private functions/variables)? And what is entry point? Thanks. /* macros ================================================== ============ */ /* constants ================================================== ========= */ /* types ================================================== ============= */ /* structures ================================================== ======== */ /* private variables ================================================== = */ /* private functions ================================================== = */ /* entry point ================================================== ======= */ /* public variables ================================================== == */ Nov 14 '05 #7

 P: n/a In 'comp.lang.c', fix wrote: Is this the order? It's not /the/ order, it's mine, but actually, my experience has shown to me that's it's hard to have another one! Does C have any privacy (private functions/variables)? sure, by the use of the 'static' word. /* macros ================================================== ============ */ /* constants ================================================== ========= */ /* types ================================================== ============= */ /* structures ================================================== ======== */ /* private variables ================================================== = */ /* private functions ================================================== = */ /* entry point ================================================== ======= */ /* public variables ================================================== == */ And what is entry point? This list was retrieved from a 'main.c' which is the source file that holds the main() function. This function being by-definition the top-level function of the application, it is also the unique entry point (the first entry) of the module. -- -ed- em**********@noos.fr [remove YOURBRA before answering me] The C-language FAQ: http://www.eskimo.com/~scs/C-faq/top.html C-reference: http://www.dinkumware.com/manuals/reader.aspx?lib=cpp FAQ de f.c.l.c : http://www.isty-info.uvsq.fr/~rumeau/fclc/ Nov 14 '05 #8

 P: n/a fix writes: Ah...... I got you, so that means if I change the content in the struct, i.e. changing the signs, denom and numerators, the pointer hasn't changed, but if I point it to NULL, I am actually changing the pointer so it reverts to the original value outside the function body. If I am to return a pointer, I am curious that if I return a pointer to a variable created inside the function, will the variable be garbage collected but the pointer still pointing to that? I was learning Java last semester and I have no trouble with pointers....... C doesn't have garbage collection. You really need to read the FAQ. This is also a FAQ. 7.5a: I have a function that is supposed to return a string, but when it returns to its caller, the returned string is garbage. A: Make sure that the pointed-to memory is properly allocated. For example, make sure you have *not* done something like char *itoa(int n) { char retbuf[20]; /* WRONG */ sprintf(retbuf, "%d", n); return retbuf; /* WRONG */ } One fix (which is imperfect, especially if the function in question is called recursively, or if several of its return values are needed simultaneously) would be to declare the return buffer as static char retbuf[20]; See also questions 7.5b, 12.21, and 20.1. References: ISO Sec. 6.1.2.4. -- "Given that computing power increases exponentially with time, algorithms with exponential or better O-notations are actually linear with a large constant." --Mike Lee Nov 14 '05 #9

 P: n/a "fix" wrote in message news: Is this the order? Does C have any privacy (private functions/variables)? And what is entry point? Thanks. The main unit of organisation for C is the file. Typically a file will contain either one complex function, or a list of related functions. For example, my BASIC interpreter has a single, very complex function, basic(const char *script), which allows a BASIC script to be run. Needless to say there are many sub-functions which that function calls, for instance there is a function to calculate the value of an algebraic expression, a function to print output, a function to execute a conditional jump. However I don't want the user to call any of these functions directly, so they are private to that file, or static. There is only one entry point, the basic() function itself. There are also private variables. For instnace the first thing I do is read all the line numbers and store them in a global array for fast access. Obviously I don't want anyone messing with that array either, so these variables are also declared static, or local to that file. Nov 14 '05 #10

 P: n/a Ben Pfaff wrote: fix writes:Ah...... I got you, so that means if I change the content in thestruct, i.e. changing the signs, denom and numerators, the pointerhasn't changed, but if I point it to NULL, I am actually changing thepointer so it reverts to the original value outside the function body.If I am to return a pointer, I am curious that if I return a pointerto a variable created inside the function, will the variable begarbage collected but the pointer still pointing to that? I waslearning Java last semester and I have no trouble with pointers....... C doesn't have garbage collection. You really need to read the FAQ. This is also a FAQ. 7.5a: I have a function that is supposed to return a string, but when it returns to its caller, the returned string is garbage. A: Make sure that the pointed-to memory is properly allocated. For example, make sure you have *not* done something like char *itoa(int n) { char retbuf[20]; /* WRONG */ sprintf(retbuf, "%d", n); return retbuf; /* WRONG */ } One fix (which is imperfect, especially if the function in question is called recursively, or if several of its return values are needed simultaneously) would be to declare the return buffer as static char retbuf[20]; See also questions 7.5b, 12.21, and 20.1. References: ISO Sec. 6.1.2.4. Thanks, where can I get the FAQ? Nov 14 '05 #11

 P: n/a Emmanuel Delahaye wrote: In 'comp.lang.c', fix wrote:Is this the order? It's not /the/ order, it's mine, but actually, my experience has shown to me that's it's hard to have another one!Does C have any privacy (privatefunctions/variables)? sure, by the use of the 'static' word./* macros ================================================== ============ *//* constants ================================================== ========= *//* types ================================================== ============= *//* structures ================================================== ======== *//* private variables ================================================== = *//* private functions ================================================== = *//* entry point ================================================== ======= *//* public variables ================================================== == */And what is entry point? This list was retrieved from a 'main.c' which is the source file that holds the main() function. This function being by-definition the top-level function of the application, it is also the unique entry point (the first entry) of the module. Aha..... thanks! Nov 14 '05 #12

 P: n/a Malcolm wrote: "fix" wrote in message news:Is this the order? Does C have any privacy (privatefunctions/variables)? And what is entry point?Thanks. The main unit of organisation for C is the file. Typically a file will contain either one complex function, or a list of related functions. For example, my BASIC interpreter has a single, very complex function, basic(const char *script), which allows a BASIC script to be run. Needless to say there are many sub-functions which that function calls, for instance there is a function to calculate the value of an algebraic expression, a function to print output, a function to execute a conditional jump. However I don't want the user to call any of these functions directly, so they are private to that file, or static. There is only one entry point, the basic() function itself. There are also private variables. For instnace the first thing I do is read all the line numbers and store them in a global array for fast access. Obviously I don't want anyone messing with that array either, so these variables are also declared static, or local to that file. Got it! thanks. Nov 14 '05 #13

 P: n/a fix writes: Thanks, where can I get the FAQ? 1. Don't quote 45 lines to add 1 line. 2. Learn to use search engines. -- "It would be a much better example of undefined behavior if the behavior were undefined." --Michael Rubenstein Nov 14 '05 #14

 P: n/a fix wrote: .... snip ... Thanks, where can I get the FAQ? Just scan the sig lines of various contributors to this newsgroup. -- Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net) Available for consulting/temporary embedded and systems. USE worldnet address! Nov 14 '05 #15

 P: n/a On Sun, 29 Feb 2004 11:13:24 -0600, fix wrote: Ben Pfaff wrote: fix writes:void normalize(Fraction *fr){ int factor; if (fr->denominator == 0) // Invalid function { fr = NULL; // set it to NULL and return printf("Set fr = NULL\n"); if (fr!=NULL) printf("Not null"); else printf("null"); return; This is in the FAQ. 4.8: I have a function which accepts, and is supposed to initialize, a pointer: void f(int *ip) { static int dummy = 5; ip = &dummy; } But when I call it like this: int *ip; f(ip); the pointer in the caller remains unchanged. A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. The called function altered only the passed copy of the pointer. You'll either want to pass the address of the pointer (the function will end up accepting a pointer-to-a-pointer), or have the function return the pointer. See also questions 4.9 and 4.11.Ah...... I got you, so that means if I change the content in the struct,i.e. changing the signs, denom and numerators, the pointer hasn'tchanged, but if I point it to NULL, I am actually changing the pointerso it reverts to the original value outside the function body.If I am to return a pointer, I am curious that if I return a pointer toa variable created inside the function, will the variable be garbagecollected but the pointer still pointing to that? I was learning Javalast semester and I have no trouble with pointers....... Almost. C passes arguments to functions by value. This means the function receives a private copy of the argument. This private copy ceases to exist when the function returns to its caller. Any change to the argument made by the function is lost when the function returns because the change was made only to the private copy which no longer exists. The original variable in the calling function was never changed and therefore never reverts. If the argument is a pointer, then the function can dereference the pointer and make "permanent" changes to the object pointed to that will persist after the function returns. There is no garbage collector in C. If you allocate memory in a function, that memory remains allocated until explicitly freed. This allocation is completely independent of function boundaries. (One frequent problem encountered is not returning the pointer to such memory which immediately creates a memory leak.) <> Nov 14 '05 #16

 P: n/a On Sun, 29 Feb 2004 11:18:25 -0600, fix wrote: Is this the order? Does C have any privacy (privatefunctions/variables)? And what is entry point?Thanks./* macros ================================================== ============ *//* constants ================================================== ========= *//* types ================================================== ============= *//* structures ================================================== ======== *//* private variables ================================================== = *//* private functions ================================================== = *//* entry point ================================================== ======= *//* public variables ================================================== == */ Functions declared static are visible only within the translation unit in which they appear. Static variables declared at file scope are visible to all functions but again only those within the same translation unit. (Static has a different meaning for variables declared inside a function.) Entry point has multiple meanings. In general, it means the definition of block of code which be the target of a reference from a different translation unit. It is how the linker resolves references to external functions. In C source code, it is a function with the external attribute (the default if static is not specified). In the context of the post you were replying to, I think the author intended something more specific and will let him comment. The important point in that message which you seem to have glossed over is that header files should not contain code or object definitions. Header files should be restricted to typedef's, prototypes, macros, and object/variable declarations. That is, they should provide descriptions but not actually generate anything. <> Nov 14 '05 #17

### This discussion thread is closed

Replies have been disabled for this discussion.