C语言中,函数不声明也能使用,但会出现warning: implicit declaration of function

转自:http://blog.csdn.net/soloopin/article/details/8057721

偶然发现有很多自定义函数未经声明却能在主程序中被调用,这就奇怪了,连使用标准库函数printf()都要包括标准输入输出头文件<stdio.h>,何况是自定义函数?这个问题困扰了我很久。

今天通过实验,基本明白了个中原因。

一、在VC6中,

1、文件test1.cpp如下:

#include "stdafx.h"           // stdafx.h: #include <stdio.h>

int Max(int x, int y)
{
       return ((x > y ) ? x : y);
}

int main(int argc, char* argv[])
{
       int a = 300, b = 100;
       printf("Max(a, b): %d/n", Max(a, b));
       return 0;
}
程序正常运行,因为Max()在被调用前已经定义。



2、将Max()移到main()之后:
#include "stdafx.h"           // stdafx.h: #include <stdio.h>

int main(int argc, char* argv[])
{
       int a = 300, b = 100;
       printf("Max(a, b): %d/n", Max(a, b));
       return 0;
}

int Max(int x, int y)
{
       return ((x > y ) ? x : y);
}
编译时出错:
error C2065: 'Max' : undeclared identifier
error C2373: 'Max' : redefinition; different type modifiers


3、在main()之前添加Max()的声明:
#include "stdafx.h"           // stdafx.h: #include <stdio.h>

int Max(int x, int y);
int main(int argc, char* argv[])
{
       int a = 300, b = 100;
       printf("Max(a, b): %d/n", Max(a, b));
       return 0;
}

int Max(int x, int y)
{
       return ((x > y ) ? x : y);
}
程序正常运行,因为Max()在被调用前已经定义。


二、在Linux中,

1、文件test2.c如下:

#include <stdio.h>

int Max(int x, int y)
{
       return ((x > y ) ? x : y);
}

int main(int argc, char* argv[])
{
       int a = 300, b = 100;
       printf("Max(a, b): %d/n", Max(a, b));
       return 0;
}
用gcc编译:gcc -Wall -o test2 test2.c,通过。程序正常运行,因为Max()在被调用前已经定义。


2、将Max()移到main()之后:
#include <stdio.h>

int main(int argc, char* argv[])
{
       int a = 300, b = 100;
       printf("Max(a, b): %d/n", Max(a, b));
       return 0;
}

 
int Max(int x, int y)
{
       return ((x > y ) ? x : y);
}

用gcc编译:gcc -Wall -o test2 test2.c,出现警告:

warning: implicit declaration of function `Max'
仍然编译通过,程序也能正常运行,因为在C语言中,当函数在调用函数之前没有声明或定义,默认作为隐式声明处理,只要在调用函数之后定义,或在别的模块中定义并编译成库文件,该库文件在调用函数所属模块编译时载入,程序即可正常运行。


用g++编译:g++ -Wall -o test2 test2.c,出现错误和警告:
error: `Max' was not declared in this scope
warning: unused variable 'Max'
没有生成可执行程序test2。因为g++使用C++的规则:函数在被调用前必须声明或定义。


三、在Linux中,采用实际工程的方式(分成若干模块)进一步实验,验证了C语言中函数在被调用前不申明也能使用。

1、在/u01/work/tools目录中,编写4个文件:

Max.c:
int Max(int x, int y)
{
       return ((x > y ) ? x : y);
}

Min.c:
int Min(int x, int y)
{
       return ((x > y ) ? y : x);
}

Add.c:
int Add(int x, int y)
{
       return (x + y);
}


Makefile:

#User defined library, by He Yaozhong
CC=gcc
HOME=/u01/work
OS=$(HOME)/tools
INCLUDE=$(HOME)/headfile -I$(HOME)/tools
CSTARGETS=Max.o Min.o Add.o
LIBS=$(HOME)/lib/tools.a
all: $(LIBS) clean

Max.o : Max.c
       $(CC) -I$(INCLUDE) -c $(CCFLAGS) Max.c

Min.o : Min.c
       $(CC) -I$(INCLUDE) -c $(CCFLAGS) Min.c

Add.o : Add.c
       $(CC) -I$(INCLUDE) -c $(CCFLAGS) Add.c

$(LIBS) : $(CSTARGETS)
       cd $(OS); /
       ar ruv $(LIBS) $(CSTARGETS:$HOME/lib/=)
clean:
       rm -f *.o


在/u01/work/tools目录中,使用make工具:


[root@node01 tools]# make

gcc -I/u01/work/headfile -I/u01/work/tools -Wall -c  Max.c
gcc -I/u01/work/headfile -I/u01/work/tools -Wall -c  Min.c
gcc -I/u01/work/headfile -I/u01/work/tools -Wall -c  Add.c
cd /u01/work/tools; /
ar ruv /u01/work/lib/tools.a  Max.o Min.o Add.o
r - Max.o
r - Min.o
r - Add.o
rm -f *.o
生成了/u01/work/lib/tools.a库文件。

2、在/u01/work/test2目录中,编写2个文件:

test2.c:
#include <stdio.h>

int main(int argc, char* argv[])
{
       int a, b;
       printf("Please input 2 integer (a, b): /n");
       scanf("%d", &a);
       scanf("%d", &b);
       printf("Max(a, b): %d/n", Max(a, b));
       printf("Min(a, b): %d/n", Min(a, b));
       printf("Add(a, b): %d/n", Add(a, b));
       return 0;
}

Makefile:
CC=gcc
HOME=/u01/work
INCLUDE=-I$(HOME)/headfile -I.
CFLAGS= -L$(HOME)/lib
LIBS=$(HOME)/lib/tools.a
all : $(OBJS) test2 clean

test2 : test2.c
       $(CC) $(INCLUDE) -Wall -o test2 test2.c $(CFLAGS) $(LIBS)

clean :
       rm -f *.o


在/u01/work/test2目录中,使用make工具:


[root@node01 func_pointer]# make
gcc  -I/u01/work/headfile -I.  -Wall -o test2 test2.c -L/u01/work/lib /u01/work/lib/tools.a
test2.c: In function `main':
test2.c:11: warning: implicit declaration of function `Max'
test2.c:12: warning: implicit declaration of function `Min'
test2.c:13: warning: implicit declaration of function `Add'
rm -f *.o


生成了/u01/work/test2/test2可执行文件。运行程序:

[root@node01 func_pointer]# ./test2
Please input 2 integer (a, b):
200
300
Max(a, b): 300
Min(a, b): 200
Add(a, b): 500

结果完全正确。

四、小结

C和C++是强类型语言,变量类型均应在代码执行前确定。
在函数声明方面C和C++则不同,C++语言中,在被调用之前未声明或定义是不允许的,而C语言是允许的。初看起来C语言这一特性是灵活、省事,但缺点是:
1、程序可读性差。
2、易出错。函数先声明再调用,是一种纠错机制,如果不声明,则没有用到这种纠错机制,虽然编译、连接通过,程序也能运行,但很可能结果不正确。

一个好的程序员,应该养成严谨、规范的编程习惯,编译程序时应打开显示所有警告选项“-Wall”,并且对编译器提出的所有警告都要给予处理,仅以编译、连接通过为目标,这可能会有潜在的危害。


五、笔记

本篇博客的意义在第四部分的总结已经写得很详细了,我看这篇博客的时候,对于第三部分涉及到makefile的模块编译没有看懂,因为makefile的语法不太懂,回头有时间再试验一下;

这儿重点说下 -I(大写的i)参数,关于这个参数的使用在之前的博客中我有提到,见:Linux下编译多个不同目录下的文件以及静态库、动态库的使用,对于本篇文章,也提到了-I参数,和之前是同样的用法——指定编译器搜索头文件的路径。不同的是这儿在主函数中没有include应有的头文件,所以在编译的时候有warning。

  • 13
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值