从random()到int的转换结果导致GCC说“警告:隐式函数定义”。为什么?

时间:2012-10-11 15:50:11

标签: c gcc c99 gcc-warning

  

可能重复:
  Why can’t gcc find the random() interface when -std=c99 is set?

我是C的新手,所以我刚进入man stdlib.h,搜索“随机”,看到random()返回long,因为这只是一次学习练习,以为我只是转换为int(而不是费心去查找返回int - rand()的那个)。

无论如何,程序编译并正确运行。但是:

$ gcc -std=c99 part1.c
part1.c: In function 'main':
part1.c:44:5: warning: implicit declaration of function 'random'

如果删除-std=99标志,它就会消失。这是“违规”代码:

  int test6[1000];
  for(i = 0; i < 1000; i++)
  {
    test6[i] = (int) random();
    printf("it is %d\n", test6[i]); //check random() is working (it isn't seeded)
  }
  printf("%d\n", largest(test6, 1000));

所以我只是想知道是否有人知道这是为什么,因为我认为这可能很有趣。

1 个答案:

答案 0 :(得分:6)

您收到warning: implicit function definition消息,因为在使用函数random()之前未声明该函数。它不是标准的C函数(不在ISO / IEC 9899:2011或其前身版本中)。你需要知道哪个头声明了它;你可能需要#define才能使声明可见。

在C99中,你必须在使用之前声明所有功能;这就是-std=c99模式对象(尽管已经发出强制诊断,它可以继续编译,可能会使函数返回int的向后兼容假设)的原因。在旧版本的C中,您不必预先声明函数;未声明的函数被隐式声明为extern int function();,这意味着'具有未指定(但不是可变)参数列表的函数返回int'。这就是编译继续做出这种假设的原因;它曾经是标准的假设。使用C99和C2011,这是正式的错误。


  

我的困惑是程序仍然可以正常编译和运行(random()也会返回伪随机数)!我在文件顶部有#include <stdlib.h>。我的#include可能无法正常工作,但是make正在做一些聪明的事情来找出它的位置吗?另一件事(我忘了提问),我认为,当我将演员表移到int时,警告最初消失了。我不能复制它,所以我想必须有一些其他的解释。也许我不小心从-std=c99或其他东西中删除了makefile

我说'标准C没有定义它';它没有,但POSIX确实如此。因此,通过包含正确的标头(<stdlib.h>),并确保看到声明,该函数从C库中获取(它不是纯粹的标准C库,而是包含很多POSIX的功能,以及GLIBC特有的许多其他功能。因此,它起作用,因为库包含该函数。您可能希望/需要使用-std=gnu99进行编译或指定#define _XOPEN_SOURCE 700#define _POSIX_C_SOURCE 200809L或类似的内容(在包含任何系统标头之前)以在random()下显示-std=c99的声明{1}}。我使用标题posixver.h将信息输入我的程序。

/*
@(#)File:           $RCSfile: posixver.h,v $
@(#)Version:        $Revision: 1.1 $
@(#)Last changed:   $Date: 2010/08/29 00:27:48 $
@(#)Purpose:        Request appropriate POSIX and X/Open Support
@(#)Author:         J Leffler
*/

#ifndef JLSS_ID_POSIXVER_H
#define JLSS_ID_POSIXVER_H

/*
** Include this file before including system headers.  By default, with
** C99 support from the compiler, it requests POSIX 2001 support.  With
** C89 support only, it requests POSIX 1997 support.  Override the
** default behaviour by setting either _XOPEN_SOURCE or _POSIX_C_SOURCE.
*/

/* _XOPEN_SOURCE 700 is loosely equivalent to _POSIX_C_SOURCE 200809L */
/* _XOPEN_SOURCE 600 is loosely equivalent to _POSIX_C_SOURCE 200112L */
/* _XOPEN_SOURCE 500 is loosely equivalent to _POSIX_C_SOURCE 199506L */

#if !defined(_XOPEN_SOURCE) && !defined(_POSIX_C_SOURCE)
#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600   /* SUS v3, POSIX 1003.1 2004 (POSIX 2001 + Corrigenda) */
#else
#define _XOPEN_SOURCE 500   /* SUS v2, POSIX 1003.1 1997 */
#endif /* __STDC_VERSION__ */
#endif /* !_XOPEN_SOURCE && !_POSIX_C_SOURCE */

#endif /* JLSS_ID_POSIXVER_H */

这是相当保守的,并没有请求POSIX 2008支持,因为我工作的一些机器没有那个 - 仍然!你可以使用它作为你的版本的基础,如果你愿意,可以更积极。我曾经直接在程序中使用了这个节,但是当安全地更改为POSIX 2008时,这就变成了一个噩梦(并且在许多源文件中明智地维护这些注释本来就很愚蠢 - 因此文件通常只包含{ {1}}只有极少或没有评论,但在变革的时候它仍然是一个改变的小提琴。)