2

可能重复:
为什么设置了 -std=c99 时 gcc 找不到 random() 接口?

我是 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));

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

4

1 回答 1

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从 themakefile或其他东西中删除了。

我说“标准 C 没有定义它”;它没有,但POSIX有。因此,通过包含正确的标头(即<stdlib.h>),并确保看到声明,该函数是从 C 库中提取的(它不是纯标准 C 库,而是包含许多 POSIX 函数,以及许多其他特定于 GLIBC 的功能)。因此,它之所以有效,是因为库包含该功能。您可能希望/需要使用-std=gnu99或指定#define _XOPEN_SOURCE 700#define _POSIX_C_SOURCE 200809L或类似的东西(在包含任何系统头文件之前)进行编译,以random()-std=c99. 我使用标题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 时,这将成为一场噩梦(并且在许多源文件中合理地维护注释本来就是愚蠢的——所以文件通常只#define _XOPEN_SOURCE 600包含很少或没有评论,但到时候改变它仍然是一个小提琴)。

于 2012-10-11T15:52:02.113 回答