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

原创 2011年04月22日 16:33:00

这段时间,在看中心后台服务软件源码时发现,有很多自定义函数未经申明却能在主程序中被调用,主程序中没有包括上述函数的头文件,我在各个目录中也找不到上述函数的头文件。这就奇怪了,连使用标准库函数printf()都要包括标准输入输出头文件<stdio.h>,何况是自定义函数?这个问题困扰了我很久。前天问中创公司奚钟华,他说:确实没有头文件,它也试过,在原来的目录中编写了一些新的函数,照葫芦画瓢地在Makefile中添加了相应项,生成了库文件,在主程序中就可调用了,其中的机理它也说不清。

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

一、在VC6中,文件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()在被调用前已经定义。

 

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

 

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中,文件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()在被调用前已经定义。

 

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

 

结果完全正确。

 

四、小结

CC++是强类型语言,变量类型均应在代码执行前确定。

在函数声明方面CC++则不同,C++语言中,在被调用之前未声明或定义是不允许的,而C语言是允许的。初看起来C语言这一特性是灵活、省事,但缺点是:

1、程序可读性差。

2、易出错。函数先声明再调用,是一种纠错机制,如果不声明,则没有用到这种纠错机制,虽然编译、连接通过,程序也能运行,但很可能结果不正确。

 

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

 

请参阅Dai Yuwen的文章:《头文件不是可有可无的》(http://daiyuwen.freeshell.org/gb/programming/about_header_files.html

错误: 隐式声明函数‘init_MUTEX’ [-Werror=implicit-function-declaration]

在新版本的linux内核中,init_mutex已经被废除了,新版本使用sema_init函数。查了一下早期版本的定义:平台:X86 32位内核:2.6.30定义:Linux/include/linu...
  • ce123
  • ce123
  • 2012年07月23日 21:33
  • 14059

GCC警告选项理解

GCC警告选项对我们及时找出代码中BUG,改善代码品质很有帮助。 听说高手们对每个警告选项都很熟悉,能灵活运用各个警告选项来分门别类地过滤代码中的BUG信息。 1 ../SRC/libpjmac...
  • buhui912
  • buhui912
  • 2013年02月18日 14:00
  • 9834

implicit declaration of function 'i2c_transfer'

今天在编译vtl_ts模块时(触摸屏)出现好多关于i2c函数没有定义的错误。 但是打开vtl_ts.c文件发现有#include 在i2c.h头文件中也发现有extern i2c_transfe...
  • qingfengtsing
  • qingfengtsing
  • 2014年12月31日 18:34
  • 1023

implicit declaration of function 这种警告问题的原因及解决方法

1  没有把函数所在的c文件生成.o目标文件2  在函数所在的c文件中定义了,但是没有在与之相关联的.h文件中声明在头文件中定义的数据只能被其他文件包含一次,但是函数可以被其他函数重复包含多次;因此,...
  • yylklshmyt20090217
  • yylklshmyt20090217
  • 2009年07月28日 16:16
  • 17352

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

转自:http://blog.csdn.net/soloopin/article/details/8057721 偶然发现有很多自定义函数未经声明却能在主程序中被调用,这就奇怪了,连使用标准库函数p...
  • baidu_35679960
  • baidu_35679960
  • 2018年01月05日 19:39
  • 38

sqlite 数据库加密(SQLCipher)

直使用sqlite来管理本地的数据,但是Xcode中的SDK中集成的sqlite是免费的,不提供加密模块,但是程序中用到的很多数据,有时候是不想让别人看到,一开始虑修改sqlite的源码,自己重新编译...
  • a6472953
  • a6472953
  • 2013年07月10日 14:27
  • 21206

多线程pthread 和 cpu affinity头文件问题

为了提高多线程程序的性能,有时候需要将线程绑定到固定的cpu core上。 在这个过程中一不小心就会产生编译的问题,但是明明头文件都定义了,却依然编译通不过。 不巧我就遇到了,google...
  • u014019422
  • u014019422
  • 2014年03月11日 08:45
  • 2028

C语言中变量和函数的声明与定义

一、变量 在将变量前,先解释一下声明和定义这两个概念。声明一个变量意味着向编译器描述变量的类型,但并不为变量分配存储空间。定义一个变量意味着在声明变量的同时还要为变量分配存储空间。在定义一个变量的同...
  • root_robot
  • root_robot
  • 2016年11月17日 21:13
  • 671

C_C语言function的使用

下面我们来介绍C语言的函数的定义与应用: 首先我们讨论一下我们为什么要使用函数,其实我们知道一个C语言本身就有一个函数main函数,他可以用来执行我们所编写的代码,那么既然如此那我们为什么还要 自己再...
  • Core__Java
  • Core__Java
  • 2014年11月12日 20:36
  • 2174

对c语言中printf函数的个人理解

对于刚刚接触c语言的人来说,printf函数应该是
  • a429491457
  • a429491457
  • 2014年10月07日 12:26
  • 1924
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C语言中,函数不申明也能使用,但会出现warning: implicit declaration of function
举报原因:
原因补充:

(最多只允许输入30个字)