【问题标题】:How to compile C code using old syntax with a modern compiler?如何使用现代编译器使用旧语法编译 C 代码?
【发布时间】:2013-06-13 18:08:00
【问题描述】:

我在 OS X 上使用 i686-apple-darwin11-llvm-gcc-4.2,我正在尝试从 this archive 编译各种程序,特别是经典的 FitCurves.c,它通过一组点拟合贝塞尔曲线。

http://tog.acm.org/resources/GraphicsGems/

一些 void 或 int 函数定义时没有返回类型,这会产生警告。

ConcaveScan.c:149:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
compare_ind(u, v) int *u, *v; {return pt[*u].y <= pt[*v].y ? -1 : 1;}

我不太确定:有一个错误

cc -g -Wno-implicit-int -Wreturn-type   -c -o AAPolyScan.o AAPolyScan.c
AAPolyScan.c:106:4: error: non-void function 'drawPolygon' should return a value [-Wreturn-type]
return;                         /* (null polygon) */

据我了解,编译器似乎认为它被隐式声明为返回 int 的函数,但该函数返回 void,从而导致错误。从声明为返回 int 的函数到 return 在 C 中有意义吗?我在这里很困惑..

我怎样才能很好地编译这个?我不一定无法编译,但警告信息量不是很大。它是使用旧语法编写的,我知道。

【问题讨论】:

    标签: c llvm


    【解决方案1】:

    您可以禁用该警告,因为您不关心它:

    -Wno-implicit-int
    

    另外,你确定你使用的是 llvm-gcc 吗?当我用您的示例进行测试时,我必须添加 -Wall 才能让 gcc 说:

    $ gcc -Wall -c -o example.o example.c
    example.c:8: warning: return type defaults to ‘int’
    

    但是clang说:

    $ clang -c -o example.o example.c
    example.c:8:1: warning: type specifier missing, defaults to 'int'
          [-Wimplicit-int]
    compare_ind(u, v) int *u, *v; {return pt[*u].y <= pt[*v].y ? -1 : 1;}
    ^~~~~~~~~~~
    1 warning generated.
    

    根本没有任何标志,并且该消息更接近您问题中的警告。在我的机器上:

    $ gcc --version
    i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
    Copyright (C) 2007 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    $ cc --version
    Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
    Target: x86_64-apple-darwin12.4.0
    Thread model: posix
    

    【讨论】:

    • 好问题。我开始手动调用它(i686-apple-darwin11-llvm-gcc-4.2)来编译单个文件,然后切换到 Makefile。我去看看
    • OK 所以Makefile调用cc,其实就是clang。
    • 好吧,这更有意义。
    【解决方案2】:

    尝试使用 -ansi 选项,该选项指定符合 1989 ANSI C 标准(相当于 1990 ISO C 标准)。旧标准允许隐式 int 和旧式函数定义。

    C99 删除了隐式 int(但奇怪的是,C99 和 C11 仍然允许旧式函数定义)。

    编译器认为它被隐式声明为一个返回 int 的函数,因为这正是它的本质,无论是在 ANSI C 之前还是在 1999 年之前的 ANSI/ISO c 中。

    但即使使用-ansi,编译器仍可能会警告定义为返回int(显式或隐式)但不返回值的函数。在 ANSI C 之前,没有 void 类型或关键字,并且不返回有意义值的函数通常在没有显式返回类型的情况下编写。旧的编译器不会警告这种常见的习惯用法。更现代的,相当合理地,这样做,因为有更好的方法来实现相同的结果:使用 void 作为返回类型定义函数。

    关于 return; 语句的投诉是错误而不是警告,因为在 C99 中,return 在非void 函数中没有表达式,或者return 中的表达式void 函数实际上是非法的(违反约束)。在 C89/C90 中,在非 void 函数中没有值的 return; 是合法的(但如果调用者尝试使用结果,则会导致未定义的行为)。

    警告消息包括用于启用它们的选项:

    warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
    ...
    error: non-void function 'drawPolygon' should return a value [-Wreturn-type]
    

    反转这些选项应该会抑制警告。指定-ansi-std=c89 也是一个好主意; gcc 目前默认为 gnu89,但在未来的版本中可能会改变。

    cc -ansi -Wno-implicit-int -Wno-return-type ...
    

    (这是基于我使用 gcc 4.7.2 的观察。我对 gcc 和 gcc-llvm 之间的关系并不完全清楚,但它们似乎采用相同的选项。)

    【讨论】:

    • 即使使用 -ansi,llvm 也会抱怨 AAPolyScan.c:106:4: error: non-void function 'drawPolygon' 应该返回一个值。 IIUC,llvm 认为它是一个 int 函数,而它实际上是一个 void 函数。不改代码就可以编译吗?
    • @Antoine:它 不是 实际上是一个 void 函数。在 C89/C90 中,没有显式结果类型的函数隐含为 int 函数。如果它不返回值,则行为是明确定义的除非调用者尝试使用结果。该警告是有效的,但不是语言要求的,并且可以选择禁止该特定警告。
    • 我的意思是写这个函数的人正在使用它,就好像被定义为 void f() 一样。他只是在某个时候返回,但 llvm 将其定义为 int f()
    • @Antoine: llvm 将其定义为 int 函数,因为这是语言指定的——即使在 ANSI C 之前(没有 void 类型或关键字)。请参阅我的更新答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 2014-03-02
    • 2022-08-13
    相关资源
    最近更新 更多