&引用;“已定义”;VC+中的错误+;
我正在学习以专业的方式编写程序。例如,通过创建单独的.C和.h文件,我决定用结构编写一个简单的代码,但我遇到了错误。 我做过这些事情:&引用;“已定义”;VC+中的错误+;,c,data-structures,C,Data Structures,我正在学习以专业的方式编写程序。例如,通过创建单独的.C和.h文件,我决定用结构编写一个简单的代码,但我遇到了错误。 我做过这些事情: /*---list.h file-------*/ #ifndef LIST_H #define LIST_H struct list{ int a; struct list *next; }; typedef struct list LIST; LIST *pHead=NULL,*pCurrent=NULL; void display(void
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
struct list{
int a;
struct list *next;
};
typedef struct list LIST;
LIST *pHead=NULL,*pCurrent=NULL;
void display(void);
#endif
/*---list.c file ---*/
#include "main.h"
void display()
{
pHead->a=100;
printf("%d",pHead->a);
}
/*----main.h file-----*/
#ifndef MAIN_H
#define MAIN_H
#include<stdio.h>
#include "list.h"
#endif
/*---main.c file---*/
#include "main.h"
void main(void)
{
LIST *New=pHead;
display();
printf("\n\n%d",New->a);
getch();
}
/*--list.h文件-------*/
#ifndef列表
#定义列表
结构列表{
INTA;
结构列表*下一步;
};
typedef结构列表;
列表*pHead=NULL,*PCCurrent=NULL;
作废显示(作废);
#恩迪夫
/*---list.c文件---*/
#包括“main.h”
无效显示()
{
pHead->a=100;
printf(“%d”,pHead->a);
}
/*----main.h文件-----*/
#ifndef MAIN_H
#定义主
#包括
#包括“list.h”
#恩迪夫
/*---main.c文件---*/
#包括“main.h”
真空总管(真空)
{
列表*新=pHead;
显示();
printf(“\n\n%d”,新建->a);
getch();
}
当我编译代码时,我得到以下错误
1> main.obj:错误LNK2005:_plist.obj中已定义电流
1> main.obj:错误LNK2005:_pHead已在list.obj中定义
谁能告诉我我做错了什么?我是否两次包含某个内容,因为这会导致重新声明错误?这是因为您在标题中定义了内容,而不仅仅是声明它们
这:
意味着每个包含列表头的C文件都试图创建两个全局变量。然后,当您将这些C文件链接在一起时,这些变量会发生冲突。这是坏的,你不应该这样做。永远不要在标题中定义内容。这是因为您在标题中定义内容,而不仅仅是声明它们
这:
意味着每个包含列表头的C文件都试图创建两个全局变量。然后,当您将这些C文件链接在一起时,这些变量会发生冲突。这是坏的,你不应该这样做。永远不要在头文件中定义对象。您在头文件中定义了对象,然后将其包含在多个源文件中,从而打破了规则
如果要创建可跨不同转换单元使用的全局变量,则应。您在头文件中定义了对象,然后将其包含在多个源文件中,从而打破了原有的规则
如果您想创建可以跨不同翻译单元使用的全局变量,您应该。一般来说,
.c
文件包含变量、函数等的具体体现。;而.h
文件包含变量、函数等的原型,可以在它的配套.c
文件中找到
通常情况下,变量和函数体不放在.h
文件中;只有变量和函数原型应该放在.h文件中
当考虑如何将代码拆分为单独的文件时,重要的是要考虑哪些函数、结构和宏是最原始的。例如,如果您编写两个函数,并且函数“a”调用函数“b”,则函数“b”是最基本的
其思想是将函数分组到一个“c”文件中,该文件是相关的,并且处于类似的原始级别
对于这个问题,更原始的列表函数应该体现在list.c
中。然后,“list.h”用于原型化其他较原始的.c
文件(如main.c
)所使用的函数和结构
最原始的函数也是最自给自足的。虽然较低级的函数应该调用较低级的函数,但反之则会导致代码流笨拙
现在回顾问题代码:
/*---list.c file ---*/
#include "main.h"
list.c
应该被认为比main.c
更原始。因此,拥有list.c
includemain.h
(专业上)不是一个好主意<代码>列表.c,更原始应该更自给自足
与其包含main.h
,不如让list.c
包含自己的list.h
,这样它就可以访问自己的“struct list”定义,等等
void display()
{
pHead->a=100;
printf("%d",pHead->a);
}
为了更好地隔离list.c
,上述函数不应引用“全局”变量(pHead)。相反,最好将“要显示的节点”作为参数传递到函数中
考虑到这一点,下面是如何改进“list.c”和“list.h”:
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
typedef struct NODE_S
{
int a;
struct list *next;
} NODE_T;
typedef struct LIST_S
{
NODE_T *head;
} LIST_T;
extern void NodeDisplay(NODE_T *node);
#endif
/*---list.c file ---*/
#include <stdio.h> // printf()
#include "list.h" // NODE_T, LIST_T
void NodeDisplay(NODE_T *node)
{
printf("%d\n",pHead->a);
return;
}
单独来看,main.h需要stdio.h
和list.h
的目的是什么?如果删除了它们,在“main.h”中是否会有“未定义”的内容?也许这两个包含文件并不真正属于main.h
。“但如果它们被从main.h中删除,为什么还要有main.h?”这是一个很好的观点。也许main.h
没有任何作用,甚至不应该存在
main.c
文件是所有文件中最基本的文件,通常不应将任何内容导出到其他(更基本的)文件
那么,main.c
到底需要什么呢?它需要调用printf()
,因此需要包含stdio.h
。它调用display()
,并引用LIST
结构,因此需要LIST.h
是的,那些.h文件包含在main.h
中;说得好。但是,如果main.c
明确地包含它所需要的内容,那么代码就不会那么笨拙(更专业)
考虑到这一理念,这里是一个经过修改的main.c
,没有多余的main.h
:
/*---main.c file---*/
#include <stdio.h> // printf()
#include <conio.h> // getch()
#include "list.h" // NodeDisplay(), LIST_T
int main(void)
{
LIST_T pList =
{
.head = NULL
};
/* Allocate & Insert a node into the list. */
NodeCreate(&pList, 100);
NodeDisplay(pList.head);
getch();
return(0);
}
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
typedef struct NODE_S
{
int a;
struct list *next;
} NODE_T;
typedef struct LIST_S
{
NODE_T *head;
};
extern void NodeDisplay(NODE_T *node);
extern void NodeCreate(LIST_T *list, int a);
#endif
为了从较不原始的main.c
调用此函数,请将此函数的原型添加到list.h
:
/*---main.c file---*/
#include <stdio.h> // printf()
#include <conio.h> // getch()
#include "list.h" // NodeDisplay(), LIST_T
int main(void)
{
LIST_T pList =
{
.head = NULL
};
/* Allocate & Insert a node into the list. */
NodeCreate(&pList, 100);
NodeDisplay(pList.head);
getch();
return(0);
}
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
typedef struct NODE_S
{
int a;
struct list *next;
} NODE_T;
typedef struct LIST_S
{
NODE_T *head;
};
extern void NodeDisplay(NODE_T *node);
extern void NodeCreate(LIST_T *list, int a);
#endif
参见扰流板代码。一般来说,
.c
文件包含变量、函数等的具体体现。;而.h
文件包含变量、函数等的原型,可以在它的配套.c
文件中找到
通常情况下,变量和函数体不放在.h
文件中;仅变量和函数原型
/*---list.c file ---*/
#include <stdio.h> // printf()
#include <stdlib.h> // malloc()
#include "list.h" // NODE_T, LIST_T
void NodeDisplay(NODE_T *node)
{
printf("%d\n",node->a);
return;
}
void NodeCreate(LIST_T *list, int a)
{
NODE_T *newNode = malloc(sizeof(*newNode));
if(NULL == newNode)
{
fprintf(stderr, "malloc(newNode) failed.\n");
goto CLEANUP;
}
if(NULL == list)
{
fprintf(stderr, "Passing NULL as the list address not allowed.\n");
goto CLEANUP;
}
/* Initialize new node fields (payload) */
newNode->a = a;
/* Link newNode as new 'list head' node. */
newNode->next = list->head ? list->head->next : NULL;
list->head = newNode;
newNode=NULL;
CLEANUP:
if(newNode)
free(newNode);
return;
}
/*---list.h file-------*/
#ifndef LIST_H
#define LIST_H
typedef struct NODE_S
{
int a;
struct list *next;
} NODE_T;
typedef struct LIST_S
{
NODE_T *head;
};
extern void NodeDisplay(NODE_T *node);
extern void NodeCreate(LIST_T *list, int a);
#endif