C struct, function pointer, and header problems (unsure which is the cause) -


so, i'm trying make binary tree program in c , keeps throwing darndest compile errors. whenever change find causing error, changes! have not forgotten include guards, used #pragma once. if place struct in header incompatible types, if put in .c redefinition of pretty_print goes away when rename pretty_print. trim out other functions in bintree.c , header, error changes inttree being undefined. if change inttree int becomes incompatible types. goes away if merge header .c. it's gone. think these might seperate errors , changing error might bad, happening have no idea why. present code demonstrates many of these, whenever try duplicate did throws different error. i'm not frustrated. able post well-formatted question helpful information, have none, despite spending several hours on program.

bintree.cxx

#include "bintree.h"  int add(inttree* root,int key,void* val){     if(!root){         root=malloc(sizeof(inttree));         if(!root){             return 1;         }         root->key=key;         root->val=val;         root->left=0;         root->right=0;         return 0;     }     if(key>root->key){         if(root->right){             return add(root->right,key,val);         }else{             root->right=(inttree*) malloc(sizeof(inttree));             if(!root->right){                 return 1;             }             root->right->key=key;             root->right->val=val;             root->right->left=0;             root->right->right=0;             return 0;         }     }     if(key<root->key){         if(root->left){             return add(root->left,key,val);         }else{             root->left=malloc(sizeof(inttree));             if(!root->left){                 return 1;             }             root->left->key=key;             root->left->val=val;             root->left->left=0;             root->left->right=0;             return 0;         }     }     return 2; }  void* get(inttree* root,int key){     if(!root){         return 0;     }     if(key>root->key){         return get(root->right,key);     }     if(key<root->key){         return get(root->left,key);     }     return root->val; }  int remove_root(inttree* root){     if(!root){         return 1;     }     if(root->right){         root->key=root->right->key;         root->val=root->right->val;         return remove_root(root->right);     }     if(root->left){         root->key=root->left->key;         root->val=root->left->val;         return remove_root(root->left);     }     free(root);     return 0; }  int remove_node(inttree* root,int key){     if(!root){         return 1;     }     if(key>root->key){         return remove_node(root->right,key);     }     if(key<root->key){         return remove_node(root->left,key);     }     return remove_root(root); }  void delete(inttree* root){     if(root){         delete(root->right);         delete(root->left);         free(root);     } }  void pretty_print(inttree* root,int ws,int wso,void (*print_val)(void*)){     if(!root) return;     printf("%*s",ws,"");     print_val(root->val);     pretty_print(root->left,ws+wso,wso,print_val);     pretty_print(root->right,ws+wso,wso,print_val); } 

bintree.h

#pragma once  #include <stdlib.h>  typedef struct inttree_s{     int key;     void* val;     struct inttree_s* left;     struct inttree_s* right; } inttree;  int add(inttree*,int,void*); void* get(inttree*,int); int remove_root(inttree*); int remove_node(inttree*,int); void delete(inttree*); void pretty_print(inttree*,int,int,void(*)(void*)); 

these throw hundreds of errors inttree being incomplete type. persists whichever format of typedef/struct use define inttree.

bintree.c

#include "pretty_print.h" void pretty_print(void){return;} 

pretty_print.h

void pretty_print(void); 

throws conflicting types "pretty_print", though not if rename "p", inline header, or change arguments "int v". works arguments "int* a,void()(void)", in original program.

final "error": warns implicit redefinition of malloc, free, printf, , puts.

bintree.cxx

struct inttree_s{     int key;     void* val;     struct inttree_s* left;     struct inttree_s* right; };  typedef struct inttree_s inttree;  int add(inttree* root,int key,void* val){     if(!root){         root=malloc(sizeof(inttree));         if(!root){             return 1;         }         root->key=key;         root->val=val;         root->left=0;         root->right=0;         return 0;     }     if(key>root->key){         if(root->right){             return add(root->right,key,val);         }else{             root->right=(inttree*) malloc(sizeof(inttree));             if(!root->right){                 return 1;             }             root->right->key=key;             root->right->val=val;             root->right->left=0;             root->right->right=0;             return 0;         }     }     if(key<root->key){         if(root->left){             return add(root->left,key,val);         }else{             root->left=malloc(sizeof(inttree));             if(!root->left){                 return 1;             }             root->left->key=key;             root->left->val=val;             root->left->left=0;             root->left->right=0;             return 0;         }     }     return 2; }  void* get(inttree* root,int key){     if(!root){         return 0;     }     if(key>root->key){         return get(root->right,key);     }     if(key<root->key){         return get(root->left,key);     }     return root->val; }  int remove_root(inttree* root){     if(!root){         return 1;     }     if(root->right){         root->key=root->right->key;         root->val=root->right->val;         return remove_root(root->right);     }     if(root->left){         root->key=root->left->key;         root->val=root->left->val;         return remove_root(root->left);     }     free(root);     return 0; }  int remove_node(inttree* root,int key){     if(!root){         return 1;     }     if(key>root->key){         return remove_node(root->right,key);     }     if(key<root->key){         return remove_node(root->left,key);     }     return remove_root(root); }  void delete(inttree* root){     if(root){         delete(root->right);         delete(root->left);         free(root);     } }  void pretty_print(inttree* root,int ws,int wso,void (*print_val)(void*)){     if(!root) return;     printf("%*s",ws,"");     print_val(root->val);     pretty_print(root->left,ws+wso,wso,print_val);     pretty_print(root->right,ws+wso,wso,print_val); } 

i can't seem generate original error, redefinition of pretty_print, again. apoligize how little know problem (basically is).

implicit redefinition of malloc, free, printf, , puts.

this means you're not including proper header files. add these every c file calls these functions.

#include <stdio.h>      // printf, puts , friends #include <stdlib.h>     // malloc/free 

don't put them in common header file - if expose type use in header file itself.

you're getting "implicit redefinition" because, if don't include proper header files, compiler implicitly define signatures based upon usage (the dumbest feature of c, imo).


people seem have hard time knowing goes in .c file , header files. it's simple:

  1. start out putting related component (e.g inttree implementation) in 1 .c file. (including structs). mark functions static means not visible outside of file.

  2. decide functions part of publicly-accessible api. remove static these functions, , copy/paste prototype .c file's accompanying .h file. (e.g. int add(inttree* root,int key,void* val);).

  3. decide if structs need visible well, or if can hidden. it's best leave actual struct definition hidden in .c file. public api functions take pointers to structures, outside code never need know size/offsets of structs. add struct foo; header file, leaving definition in .c file.

example:

foo.c

#include "foo.h"  /** definition of struct foo - hidden consumers of foo **/ struct foo {     int a;     int b;     int c; };             /* gets forgotten :-) */  /** "private" internal function, marked static hide consumers **/ static void _foo_internal(struct foo *f) {     // ... internal function **** }  /** foo public api **/ struct foo *new_foo(int a, int b, int c) {     struct foo* f;      f = malloc(sizeof(*f));     if (f == null)         return null;      _foo_internal(f);     f->a = a;     f->b = b;     f->c = c; }  int foo_get_a(struct foo *f) {     _foo_internal(f);     return f->a; }  void foo_set_a(struct foo *f, int val) {     _foo_internal(f);     f->a = val; } 

foo.h

#ifndef foo_h #define foo_h  /**  * consumers need know struct foo exists,  * not size of member offsets.  */ struct foo;  /** prototypes foo public api **/ struct foo *new_foo(int a, int b, int c); int foo_get_a(struct foo *f); void foo_set_a(struct foo *f, int val);  #endif /* foo_h */ 

test.c

#include "foo.h"  int main(void) {     /**      * no static instances of foo allowed!      * test.c not know size of struct foo!      */     //struct foo my_foo;      struct foo *pfoo;      pfoo = new_foo(1,2,3);     if (pfoo == null)         return 1;      set_foo_a(pfoo, 42);      return 0; } 

Comments

Popular posts from this blog

commonjs - How to write a typescript definition file for a node module that exports a function? -

openid - Okta: Failed to get authorization code through API call -

thorough guide for profiling racket code -