I've decided to go through all of D&R's exercises and in doing so I have encountered a peculiar event. Based on the book's own addtree function I modified it for my own structure:
struct gnode {
char **words;
int count;
struct gnode *left;
struct gnode *right;
};
And it now is:
struct gnode *addtree(struct gnode *p, char *w) {
int cond;
if (p == NULL) {
printf("init null node\n");
p = (struct gnode *)malloc(sizeof(struct gnode));
//MISTAKE I WAS MAKING:
// struct gnode *p =(struct gnode *)malloc(sizeof(struct gnode));
//p would be NULL every time.
p->count = 1;
p->words = malloc(8);
p->words[0] = strdup2(w);
p->left = p->right = NULL;
} else
if ((cond = compare(w, p->words[0])) == 0) {
printf("comp hit\n");
p->count ;
p->words = realloc(p->words, p->count * 8);
p->words[p->count] = strdup2(w);
} else
if (cond < 0)
p->left = addtree(p->left, w);
else
p->right = addtree(p->right, w);
return p;
}
I would like to know why if a local pointer with the same name as the argument is returned, it is NULL every time.
CodePudding user response:
There are multiple issues in your code:
when the tree is empty, the line in the original code
struct gnode *p = (struct gnode *)malloc(sizeof(struct gnode));allocates a newgnodeobject, but also defines a new identifierpwith a local scope, effectively shadowing the argument name. Hence the argument variablepis not updated and ultimately the original value (a null pointer) is returned byreturn p;at the end of the function.You can prevent this type of silly mistake by increasing the compiler warning level:
gcc -Wall -Wextraorclang -Weverythingthe allocation
p->words = malloc(8);is not portable. You should use:p->words = malloc(sizeof(*p->words));same for
p->words = realloc(p->words, p->count * 8), it should bep->words = realloc(p->words, p->count * sizeof(*p->words));furthermore, since
p->countwas already incremented, setting the duplicate word should use:p->words[p->count - 1] = strdup2(w);why use
strdup2(w)instead ofstrdup(w)?wshould probably be defined asconst char *w.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct gnode {
char **words;
int count;
struct gnode *left;
struct gnode *right;
};
struct gnode *addtree(struct gnode *p, const char *w) {
int cond;
if (p == NULL) {
printf("init null node\n");
p = malloc(sizeof(*p));
p->count = 1;
p->words = malloc(sizeof(*p->words));
p->words[0] = strdup2(w);
p->left = p->right = NULL;
} else
if ((cond = compare(w, p->words[0])) == 0) {
printf("comp hit\n");
p->count ;
p->words = realloc(p->words, p->count * sizeof(*p->words));
p->words[p->count - 1] = strdup2(w);
} else
if (cond < 0) {
p->left = addtree(p->left, w);
} else {
p->right = addtree(p->right, w);
}
return p;
}
CodePudding user response:
I would like to know why if a local pointer with the same name as the argument is returned, it is NULL everytime.
You weren't returning a local variable.
You created a local variable, set it to allocated space, and used it to set some fields.
Then its scope ended at the end of the if block. It no longer shadowed the outer variable.
The outer variable p was never modified from its original null value.
You can avoid this by not shadowing variables.
