没有头文件,为什么能运行?
我在dev c++中建立了一个控制台c工程,只写了两个文件如下所示,没有任何头文件,也没有用extern声明ppp函数,但是却能执行,请问高手这是为什么?
main.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
ppp();
system("PAUSE");
return 0;
}
1.c
void ppp()
{
printf("%d\n",1);
}
问题点数:100、回复次数:32Top
1 楼ammana_babi(郑诤)回复于 2006-09-25 12:23:30 得分 0
兄弟,在我这儿编译是通不过的,从语法来说,编译通过也是不可能的。Top
2 楼gofqjyie(誓将天下了然于胸)回复于 2006-09-25 12:25:08 得分 0
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
ppp();
system("PAUSE");
return 0;
}
void ppp()
{
printf("%d\n",1);
}
是在一个文件中的吗?是当然能执行了
Top
3 楼lhbgyl(古城)回复于 2006-09-25 12:26:49 得分 0
我是建立了一个工程文件的Top
4 楼lhbgyl(古城)回复于 2006-09-25 12:27:40 得分 0
不是在一个文件中,主函数在main.c中,ppp()在1.c中Top
5 楼lann64(昆仑大鹏@迦楼罗)回复于 2006-09-25 12:36:45 得分 0
应该可以的,编译器会给出警告而已。但连接器会找到连接点,最终能够生成可执行程序。
gcc就是这样实现的。虽然不严格符合标准。Top
6 楼Arthur_()回复于 2006-09-25 12:47:26 得分 0
dev c在你建立工程的時候為你做了好多事情Top
7 楼mLee79()回复于 2006-09-25 12:55:03 得分 0
C 遇到未申明的函数时, 自动认为是 int func();
gcc 的实现符合标准, 没遇到过不能过的编译器, 一般都给个警告, 不是好习惯 ...
Top
8 楼lhbgyl(古城)回复于 2006-09-25 12:56:13 得分 0
我在DEV中不打开工程文件,直接打开main.c和1.c文件,用extern 和头文件方式都试过了,都不能编译,请问工程文件是c语言中必需的吗?c的书籍里怎么没有说工程文件是必需的呢?Top
9 楼Arthur_()回复于 2006-09-25 12:57:46 得分 5
不建立工程要有makefile文件,看一下吧Top
10 楼lj860603(跑吧,键键)回复于 2006-09-25 13:04:17 得分 0
有的编译器可能把一些头文件自动加进去了。要看具体情况。Top
11 楼wanfustudio(雁南飞:知识之败,慕虚名而不务潜修也)回复于 2006-09-25 14:35:30 得分 0
编译器若的祸
害得你全然不知Top
12 楼jixingzhong(瞌睡虫·星辰)回复于 2006-09-25 18:40:06 得分 0
建立了工程,是可以的,
楼主你若没有工程,
只是单独的源文件, 那么就 Over 了 ...
关键是工程管理为你做了这些工作 ~Top
13 楼OOPhaisky(异化$渴望成功~~)回复于 2006-09-25 18:55:22 得分 0
编译器/编译环境的问题。Top
14 楼lhbgyl(古城)回复于 2006-09-25 20:13:39 得分 0
那么请问各位高手,可不可以在dev c++下不建立工程,只写几个单独的源文件来生成代码?如果可以,如何作,是不是写makefile文件啊。我最想知道的是工程文件是为了编程方便,厂家加的东西,还是c语言本身就规定了要有工程文件,前面Arthur_(凉咖啡)说不建立工程文件就用makefile,那么makefile是c语言本身规定的东西吗?我在看书的时候没有发现有这些啊,那么如果不用这两种方式就没有办法组织c程序了吗?请高手给予解答。Top
15 楼antee(antee)回复于 2006-09-25 21:20:39 得分 0
main.c应该编译不过的,除非ide或者编译器做了其它处理.Top
16 楼crazy_lazy_pig(疯狂懒猪)回复于 2006-09-25 21:55:38 得分 40
编译时, dev c++ 内部是用了类似于下面的命令:
(cc) main.c l.c
其中(cc)是dev c++ 所采用的编译器的名子(可执行文件), 我这里省略了一些参数, 因为我不清楚dev c++用的是什么编译器.
这个命令的意思是分别编译(即只生成目标代码)main.c 和 l.c , 然后连接两个目标文件(也许还包括一些默认的库), (连接的意思就是把所需的具体的函数实现连接成一个可执行文件,这些实现可能在目标文件里,也可能在库里).
此例中, ppp()由main()调用, 它的具体实现在l.c中, 而(cc) main.c l.c 命令生成了两个目标文件main.o l.o, 当main()需要ppp()的时候, 编译器会在main.o和l.o里自动寻找ppp()的实现, 所以编译成功是没问题的.
如果仅用命令编译main.c, 像这样: (cc) main.c 那么估计编译就不通过了, 会报告说ppp()的定义找不到.Top
17 楼lw1a2(一刀 现在改六点下班了:()回复于 2006-09-25 22:00:47 得分 15
工程,相当于帮你写了MakefileTop
18 楼123ppmove(迷茫)回复于 2006-09-26 08:13:38 得分 0
Makefile
不是linux下用的?
VC识别不了吧?
你用turborC试试;Top
19 楼mLee79()回复于 2006-09-26 09:12:09 得分 0
C 本来就不需要声名函数, 啥编译器编译不过, 俺倒没遇到过 ....
当main()需要ppp()的时候, 编译器会在main.o和l.o里自动寻找ppp()的实现
----------------------------------------------------------------------
显然不对, 编译 main.c 的时候跟 l.c 一点关系都没有, 编译器会自动声名 ppp 的原型为 int ppp() , 并给个警告啥的 ...
Top
20 楼sharkoasis(魔师庞斑)回复于 2006-09-26 10:08:23 得分 0
在工程中应该是可以编译通过的!Top
21 楼lann64(昆仑大鹏@迦楼罗)回复于 2006-09-26 10:58:31 得分 0
唉,k&R标准、c89标准还是如此深入人心呀。什么函数不用声明返回类型,函数前向声明不用声明调用参数的,这些在c99标准已经修改了的东东,现在还是有很多人抱着不放。而且还有人认为c本来就是这样,那些要求是从c++里的。是的,c++要求,可c99也已经改成要求了。用c的朋友们,还是改改自己的习惯,向c99靠齐吧。Top
22 楼waterczh(三十年河东三十年河西,我TMD是掉到河里了)回复于 2006-09-26 12:01:58 得分 0
MARKTop
23 楼lhbgyl(古城)回复于 2006-09-26 13:37:52 得分 0
怎么大家的解释都不一样啊,另外大家都没有回答我的问题:如果没有工程文件和makefile文件,怎么把几个c程序组织起来,还有c标准中是否提到了一定要工程文件或者makefile文件?Top
24 楼crazy_lazy_pig(疯狂懒猪)回复于 2006-09-26 14:40:36 得分 0
To: mLee79()
多谢你的指导,我是自学者,而且不愿意看书,所以很多东西都是凭个人揣测的,关于提前声明和编译警告的事我确实是没有注意. 不过我说的"自动寻找ppp()的实现"是指连接过程,而不是编译过程.
to: 楼主
看情况, 楼主是不理解编译和连接,英文里编译用compile,连接用link, 这是两个完全不同概念,而中的教材往往把这两个过程合称"编译",这是不对的.
楼主问的"怎么把几个C程序组织起来", 其实就是连接问题. 对于写好的C源代码, 我们首先要编译,即生成目标代码(一种中间代码,需进一步处理而成可执行的机器代码); 然后把目标代码文件(可能是好几个)中的函数连接成有实际功能的可执行代码. 具体做法如下(以gcc编译器为例):
gcc -c main.c
gcc -c l.c
gcc -o test.exe main.o l.o
上面给出的是命令行下要敲的三条命令,其中main.o和l.o是编译过程(即前两个命令gcc -c ...)生成的中间代码文件, 最后的test.exe是最终连接生成的可执行文件,在命令行下继续敲test.exe就可以看到结果了.
make文件里其实就是存贮了上面的三行命令,它是通过另外一个叫make程序的程序调用,解释执行这三条命令,其实跟在命令行下直接敲这三行命令是等价的;工程文件其实实现的就是make文件的功能,也就等价于命令行下敲这三个命令. 因此可以的结论: 工程文件跟make文件其实跟c语言没有什么大的联系,这只是为了使我们使用的方便而出现的第三方管理工具(试想,如果我们有几十甚至上百个源文件,那么在从命令行下敲那些命令是不是太累了), 我们可以用它来简化操作,但是也完全可以不用.Top
25 楼crazy_lazy_pig(疯狂懒猪)回复于 2006-09-26 14:46:55 得分 0
另外, 楼主: 上面有几个人批评了你的写代码的规范问题,不知道你是否有注意.
就是说在main()函数之前应该加入一个提前声明:
void ppp();
注意,C语言是严格类型语言,在使用任何东西之前必须先声明,这才是好的代码规范.
(而是不是有头文件并不重要,其实头文件的作用就是让你少写几个字或者使一些代码方便于重复利用, #include完全等价于你把头文件里的内容拷贝到现有文件中去).Top
26 楼lhbgyl(古城)回复于 2006-09-26 16:29:15 得分 0
谢谢各位的解答,我已经清楚了Top
27 楼mLee79()回复于 2006-09-26 16:32:12 得分 0
lann64(昆仑大鹏) :
C99 标准什么时候对此进行了修改, C99 只是不在支持 func() == int func() 而已, 绝对没有禁止调用未声明的函数, C 也显然没有向 cpp 靠拢的迹象 ...
P499 , Common warnings 下明确的写着 :
— A function is called but no prototype has been supplied (6.5.2.2).
标准仅仅要求对未声明的函数调用给出一个警告而已 .....
Top
28 楼lhbgyl(古城)回复于 2006-09-26 16:39:08 得分 0
鉴于讨论未结束,暂不结贴,请大家继续讨论,多学知识,先加50分,如果能讨论出有启发的东西,再加分Top
29 楼lann64(昆仑大鹏@迦楼罗)回复于 2006-09-26 16:42:10 得分 0
mLee79()
C99 标准什么时候对此进行了修改, C99 只是不在支持 func() == int func() 而已, 绝对没有禁止调用未声明的函数, C 也显然没有向 cpp 靠拢的迹象 ...
============================
我没说“禁止调用未声明的函数”,我说的是“函数前向声明不用声明调用参数”被c99完全放弃了。按照k&R标准 int foo(int i,int j)这样的函数前向声明是可以为 int foo()这样的,这种声明在c99中被认为是出错。我哪里说错了?
至于c有没有向c++靠拢,个人理解去吧。我没说过,你要这样理解,随你了。
不知道是我说的不清楚,还是你的理解力有问题。Top
30 楼mLee79()回复于 2006-09-26 16:52:50 得分 20
很抱歉的是 标准里明确支持 int foo() 作为 int foo( int , int ) 的声明 , 并且我认为在以后的标准中, 这一点也不会有任何的修改 ....Top
31 楼lann64(昆仑大鹏@迦楼罗)回复于 2006-09-26 17:21:43 得分 20
6.11.6 Function declarators
1 The use of function declarators with empty parentheses (not prototype-format parameter
type declarators) is an obsolescent feature.Top
32 楼Nash1983()回复于 2006-09-27 12:39:26 得分 0
编译器不严格,如果改成.cpp就通不过了Top




