【问题标题】:What is -D__USE_FIXED_PROTOTYPES__ in GCC used for?GCC 中的 -D__USE_FIXED_PROTOTYPES__ 是做什么用的?
【发布时间】:2018-06-11 10:00:02
【问题描述】:

Practical C Programming的书Chapter 7 Programming Process中有一个makefile:

File: calc1/makefile.gcc
#-----------------------------------------------#
#   Makefile for unix systems       #
#    using a GNU C compiler         #
#-----------------------------------------------#
CC=gcc
CFLAGS=-g -D__USE_FIXED_PROTOTYPES__ -ansi
#
# Compiler flags:
#   -g  -- Enable debugging
#   -Wall   -- Turn on all warnings (not used since it gives away
#           the bug in this program)
#   -D__USE_FIXED_PROTOTYPES__
#       -- Force the compiler to use the correct headers
#   -ansi   -- Don't use GNU extensions.  Stick to ANSI C.

calc1: calc1.c
    $(CC) $(CFLAGS) -o calc1 calc1.c

clean:
    rm -f calc1 

什么是“正确的标题”?为什么选项参数-D__USE_FIXED_PROTOTYPES__之间没有空格?

GCC mirror中,有:

/* __USE_FIXED_PROTOTYPES__ used to be required to get prototypes for
   malloc, free, etc. on some platforms.  It is unclear if we still
   need it, but it can't hurt.  */
#define __USE_FIXED_PROTOTYPES__

Re: Is __USE_FIXED_PROTOTYPES__ really necessary?有解释。

但我没有得到分数。

这本 PRACC 书出版于 1997 年,有点旧,但仍然非常有用。 Makefile 有点过时了,不知道是否还需要 .gcc 扩展名。

Errata for Practical C Programming 中均未提及这些。

【问题讨论】:

  • -D__USE_FIXED_PROTOTYPES__ 之间的空格是可选的。请注意,从某种意义上说,-ansi 标志已过时,您现在应该使用-std=c90(或多或少是-ansi 的意思)或-std=c99-std=c11(最好是后者)之一,或 GNU 变体之一(例如 -std=gnu11 — 这是 GCC 7(以及 6、和 5 IIRC,但在早期版本中不是默认值)中的默认值。
  • 2017年用1997年的编程书,2018年的错误,就像用1307年的建筑书一样。
  • .gccmakefile 的后缀可能用于允许为不同的编译器编写不同的makefile。如果您打算使用 GCC,则确实不需要后缀。它唯一的危害是你必须输入make -f makefile.gcc 而不仅仅是make——至少在你输入ln -s makefile.gcc makefile(或mv makefile.gcc makefile)之前是这样。 __USE_FIXED_PROTOTYPES__ 的东西在 20 年前似乎是必要的;不过,在这个千年的大部分时间里,这并不是必需的。从生成文件中删除它;它是现在无关紧要的历史材料。
  • 您能否明确说明您使用这本书的哪个版本?是不是第三个?

标签: c unix gcc makefile


【解决方案1】:

所有这些都是错误的。我不知道在 2018,即 2011 年最新版本发布年份的第 7 年,强制编译器坚持已弃用的 1989 年标准修订版有什么实际意义。

__USE_FIXED_PROTOTYPES__ 的必要性似乎已经讨论过in 1997。这是为了使代码在头文件早于 1989 年标准的平台上工作。你不会需要它的。那时你可以有一个执行以下操作的程序:

#include <stdlib.h>
int main() {
    void *p = malloc(42.0);
}

并且程序将具有未定义的行为,因为&lt;stdlib.h&gt; 不包含原型,并且参数类型错误。

现在 GCC 不能那样工作了。从 C99 开始,如果缺少原型,GCC 就会大声抱怨。它还会抱怨错误的参数类型等:

// #include <stdlib.h>
int main() {
    void *p = malloc(42.0);
}

编译时:

% gcc test.c 
test.c: In function ‘main’:
test.c:2:15: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
     void *p = malloc(42.0);
               ^~~~~~
test.c:2:15: warning: incompatible implicit declaration of built-in function ‘malloc’
test.c:2:15: note: include ‘<stdlib.h>’ or provide a declaration of ‘malloc’

使用-pedantic-errors,隐式函数声明会变成一个错误,导致编译失败(应该如此)。

我什至不确定这是否真的有任何影响。大概这是为了修复声明,以便每当您包含 &lt;stdlib.h&gt; 时,这也意味着例如 malloc 将有一个正确的原型,而不是隐式函数声明。在 20 年前为 15 岁的系统编译时,它可能是相关的。现在它在为 35 岁的系统编译时是相关的。

如果这是本书给出的实用建议,我的实用建议是将其用作燃烧过程的燃料。这可能是您可以用它做的最有用的事情。

如果您重视标准符合性,请使用

,而不是所有这些标志
-Wall -std=c11 -pedantic-errors

没有-pedantic-errors,即使-std=c11 -Wall 也会允许某些GCC 特定的扩展通过。

【讨论】:

  • 您对包含包含的代码的“不包含”评论可能有点令人困惑。而且您过去需要编写 extern char *malloc(); 才能获得正确的准标准返回类型 - 在 C90 之前它不是 void *,并且没有声明它的标准标头。
  • @JonathanLeffler 啊,那只是一句残句,2018年有时间校对。
猜你喜欢
  • 1970-01-01
  • 2011-11-17
  • 1970-01-01
  • 2011-05-07
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 2018-10-16
  • 2011-08-24
相关资源
最近更新 更多