所以,我试图用 C 编写这个二叉树程序,但它一直抛出最糟糕的编译错误。每当我更改某些内容以查找导致错误的原因时,它就会发生变化!我没有忘记我的 include 守卫,我用过一次#pragma。如果我将结构放在 header 中,我会得到不兼容的类型,如果我把它放在 .c 中,我会得到 pretty_print 的重新定义,当我重命名 pretty_print 时它会消失。当我删除 bintree.c 和 header 中的其他函数时,错误更改为 intTree being undefined。如果我然后将 intTree 更改为 int,它就会变成不兼容的类型。如果我将 header 合并到 .c 中,这就会消失。现在它不见了。我认为这些可能是单独的错误,而不断变化的错误可能是我的错,但它正在发生,我不知道为什么。我将提供演示其中许多内容的代码,但每当我尝试复制我所做的事情时,它都会抛出不同的错误。但我并不沮丧。我希望能够发布一个格式正确的问题和有用的信息,但我没有一个,尽管在这个程序上花了几个小时。
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*));
这些会引发数百个有关 intTree 是不完整类型的错误。这适用于我用来定义 intTree 的任何 typedef/struct 格式。
bintree.c
#include "pretty_print.h"
void pretty_print(void){return;}
pretty-print .h
void pretty_print(void);
抛出“pretty_print”的冲突类型,但如果我重命名为“p”、内联标题或将参数更改为“int v”则不会。这也适用于原始程序中的参数“int* a,void()(void)”。
最后的“错误”:对 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);
}
我似乎无法再次生成原始错误,该错误是关于 pretty_print 的重新定义。对于我对这个问题知之甚少(基本上就是这样),我深表歉意。
最佳答案
implicit redefinition of malloc, free, printf, and puts.
这意味着您没有包含正确的头文件。将这些添加到调用这些函数的每个 C 文件中。
#include <stdio.h> // printf, puts and friends
#include <stdlib.h> // malloc/free
不要将它们放在一些通用的头文件中 - 仅当它们公开您在头文件本身中使用的类型时才这样做。
你会得到一个“隐式重定义”,因为如果你不包含正确的头文件,编译器将根据你的使用隐式定义它们的签名(C 的最愚蠢的特性,海事组织)。
人们似乎很难知道 .c
文件和头文件中的内容。很简单:
开始将与此组件相关的所有内容(例如您的 intTree 实现)放在一个
.c
文件中。 (包括struct
)。将所有函数标记为static
,这意味着它们对文件外部的任何人都不可见。确定哪些函数是您可公开访问的 API 的一部分。从这些函数中删除
static
,并将它们的 prototype 复制/粘贴到该.c
文件的随附.h
文件。 (例如int add(intTree* root,int key,void* val);
)。决定是否有任何
struct
也需要可见,或者它们是否可以隐藏。最好将实际的struct
定义隐藏 保留在.C 文件中。您的公共(public) API 函数将只接受指向这些结构的指针,因此外部代码永远不需要知道那些struct
的大小/偏移量。所以只需将struct foo;
添加到头文件中,将其定义留在 .C 文件中。
例子:
foo.c
#include "foo.h"
/** Definition of struct foo - hidden to consumers of foo **/
struct foo
{
int a;
int b;
int c;
}; /* This always gets forgotten :-) */
/** "private" internal function, marked static to hide from 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 to know only that struct foo exists,
* not its size of member offsets.
*/
struct foo;
/** Prototypes for 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 */
测试.c
#include "foo.h"
int main(void)
{
/**
* No static instances of foo allowed!
* test.c does not know the 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;
}
关于C 结构、函数指针和头文件问题(不确定是哪个原因),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23986575/