关于 多文件编译 #ifndef 的几个疑问

huanhuan30 2009-04-10 03:16:38
对 多文件编译 一直有疑问...
看了 http://www.cppblog.com/twzheng/archive/2007/05/07/23584.html 这篇文章.我更是疑问..

“头件的中的#ifndef,这是一个很关键的东西。比如你有两个C文件,这两个C文件都include了同一个头文件。而编译时,这两个C文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。” ————这一段是我从刚刚那个文章里复制下来的...

他说会产生 大量的声明冲突.... 我 写了一个 a.h ,内容如下



//———names.h———————

#define SLEN 32
struct name_st
{
char first[SLEN];
char last[SLEN];
};

typedef struct name_st names;

void get_name(names *);
void show_name(names *);

....随便写 a.c 和b.c 都包含有#include <names.h> 这一句
但是 编译成一个EXE后。。就是不出错。。
照这篇文章里面的说法。。我的 a.c和b.c 里都 有一个 names 这样一个数据结构....为什么编译可以成功呢?非常不懂
...全文
162 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
wangyadong 2009-04-10
  • 打赏
  • 举报
回复
编译器虽然是单独编译,但是也可以发现重复包含的问题,我测试了一下,对于类的定义,结构体的定义重复包含都是没有问题的,对于宏,kiffa说的对,在编译的时候已经替代,也是没有问题的,函数也可以重复声明,有问题的是对变量的定义,如果你的.h文件包含变量的定义,就会出现错误,当然重复声明始终是没有问题的,一个原则,分配内存的在.ccp中,不分配的在.h中
zhirom 2009-04-10
  • 打赏
  • 举报
回复
xuexi
ctan 2009-04-10
  • 打赏
  • 举报
回复
到底是a.h,
还是#include "names.h"
???
xiaocha 2009-04-10
  • 打赏
  • 举报
回复
下面的说法,仅限于 C,C++有些不同,不一定行!

你把 names 复制成两个文件: names_a.h names_b.h
分别给 a.c 和 b.c 使用,
同时任意修改 name_st 的字段名,让两个文件不同,
当然为避免语法错误,a.c 和 b.c 作相应修改,
你仍然可以得到可以工作的exe文件

实际上,编译器是单独编译两个文件,生成目标文件 a.obj, b.obj
可以说编译 a.c 和 编译b.c 一点关系都没有,
然后,编译器连接 a.obj b.obj 生成 exe 文件
对于编译器来说,知道全局函数get_name就行了,它的参数就不管了(再次说明,仅限于 C,C++不同)

甚至,你可以让 a.c 和 b.c 中的 get_name 声明完全不同
例如:(当然要保证 a.c 和 b.c没有语法错误)
a.c 定义并声明 void get_name(names *pn);
b.c 声明 void get_name(int a);
同样可以生成 exe 文件,但这样的程序工作起来肯定有问题。
使用共同的头文件,就是为了避免这样的错误

“大量的声明冲突”,这句话不准确,应该说是"大量的定义冲突"比较好,
因为在 C 中,变量和函数的重复声明一般没有问题(对于一次单独编译,必须声明一致),但重复定义就一定有问题!
例如: 写多少遍 extern int i; void func(int a); 都没有问题
kiffa 2009-04-10
  • 打赏
  • 举报
回复
头文件中放类定义(结构定义)当然不会引发重定义的错误。。。

你的头文件中:
#define SLEN 32

属于宏,编译前就替换掉了,链接时当然不会产生重定义的错误。

struct name_st { ... }; 和 typedef struct name_st names; 

类定义和typedef都属于内部链接,不会导出到链接符号表,因此不会产生重定义的错误。

void get_name(names *);
void show_name(names *);

都只是函数声明,C++不能重复定义,但可以重复声明。

你首先必须要弄明白重定义是怎样产生的,特别是多文件之间的重定义。




huanhuan30 2009-04-10
  • 打赏
  • 举报
回复

// a.c
#include <stdio.h>
#include "stdafx.h"
#include "names.h"
void get_name(names *pn)
{
int i;
printf("please enter the first name.\n");
fgets(pn->first, SLEN, stdin);
i = 0;
while(pn->first[i] != '\0' && pn->first[i] != '\n')
{
i++;
}
if(pn->first[i] == '\n')
{
pn->first[i] = '\0';
}
else
{
while(getchar() != '\n')
continue;
}
printf("please enter last name.\n");
fgets(pn->last, SLEN, stdin);
i = 0;
while(pn->last[i] != '\n' && pn->last[i] != '\0')
{
i++;
}
if(pn->last[i] == '\n')
{
pn->last[i] = '\0';
}
else
{
while(getchar()!= '\n')
continue;
}
}
void show_name(names *pn)
{
printf("%s %s", pn->first, pn->last);
}


//b.c
#include <stdio.h>
#include "stdafx.h"
#include "names.h"


int main(void)
{
names candidate;
get_name(&candidate);
printf("welcome to here.\n");
show_name(&candidate);
return 0;
}
  • 打赏
  • 举报
回复
没研究过什么时候会重定义.
一般都会写ifndef.
你试下把names.h改成a.h
Rain208 2009-04-10
  • 打赏
  • 举报
回复
把你的a.c和b.c 贴上看看

69,381

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧