没有来自拆分源的输出,但在省略包含的文件时也没有警告

No output from split up source, but no warnings either, when omitting an included file

提问人:Scott Prive 提问时间:8/14/2022 更新时间:8/14/2022 访问量:45

问:

我在调用 gcc 时遇到了一个问题,如果我省略库文件,我就没有从二进制文件中得到任何输出(意外的行为更改),但由于这是一个缺少的依赖项,我有点期望编译会失败(或至少警告).......c

此问题的示例来自 Head First C 第 185 页(但不是勘误表,请参阅下面的编译错误步骤):

encrypt.h:

void encrypt(char *message);

encrypt.c:

#include "encrypt.h"

void encrypt(char *message)
{
    // char c; errata
    while (*message) {
        *message = *message ^ 31;
        message++;
    }
}

message_hider.c:

#include <stdio.h>
#include "encrypt.h"

int main() {
    char msg[80];
    while (fgets(msg, 80, stdin)) {
        encrypt(msg);
        printf("%s", msg);
    }
}

现在,如果我按照练习说明忠实地编译,一切正常:

gcc message_hider.c encrypt.c -o message_hider

...但是运气不好,我只编译了主要的.c文件,如下所示:

$ gcc message_hider.c -o message_hider
  1. 这出人意料地成功构建,即使我添加了.-Wall -Wextra -Wshadow -g
  2. 同样令人惊讶的是,它静默地失败了,encrypt() 函数没有输出:
$ ./message_hider < ./encrypt.h 
$ 

我的GCC是:

$ /usr/bin/gcc --version
Apple clang version 13.1.6 (clang-1316.0.21.2.5)
Target: x86_64-apple-darwin21.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

请注意,即使使用 Makefile,由于配方中的错误,我“仍然”可能最终丢失 .c 文件。

问:如果我忘记告诉文件,是否可以强制执行硬错误?gcc.c

c gcc 依赖项 警告

评论

2赞 Jonathan Leffler 8/14/2022
系统库中可能有一个函数。encvrypt()
0赞 Scott Prive 8/14/2022
@JonathanLeffler 好答案!我只是将所有内容重命名为“encryptx”(头文件名、函数和原型),然后只编译主 .c 文件,现在失败并显示 .非常好!随意更改为答案。如果您的函数与系统库中的内容同名,有没有办法强制发出错误/警告?Undefined symbols for architecture x86_64: _encryptx"
0赞 Scott Prive 8/14/2022
奇怪的是,我在 stdio.h 或 stdio.h 包含的文件中没有看到任何其他文件encrypt()
1赞 Jonathan Leffler 8/14/2022
没有任何简单的方法可以获取有关您无意中使用的系统库中定义的函数的警告。对于记录在案的函数(例如;对于未记录的(“本应是内部的”)函数名称冲突,情况就更糟了。(几十年前),我必须解决的一个更阴险的错误涉及一个“我们内部”的函数,称为“他们内部”系统库——这两个函数的工作完全不同。这需要大量的追踪工作。我们重命名了内部函数,现在我避免使用以 开头的名称。encrypt()_bind()_

答:

3赞 Jonathan Leffler 8/14/2022 #1

正如我在(拼写错误的)评论中指出的那样:

系统库中可能有一个函数。encrypt()

在 Mac 上,显示:man -s 3 encrypt

CRYPT(3) BSD 库函数手册 CRYPT(3)

NAME
crypt, encrypt, setkey -- DES 加密

概要

#include <unistd.h>

char *
crypt(const char *key, const char *salt);

void
encrypt(char *block, int edflag);

#include <stdlib.h>

void
setkey(const char *key);

...

encrypt() 和 setkey() 函数是 POSIX 的一部分,因此它们在大多数类似 POSIX 的系统上都可用。奇怪的是,如手册页摘录中所示,这些函数是在单独的标头中声明的 — <unistd.h> for 和 <stdlib.h> for 。 断开连接可能有一个很好的(足够)的历史原因。encrypt()setkey()

您应该已经收到有关函数未声明的编译器警告 - 如果您没有,您可能正在使用 C90 标准进行编译。这是很古老的,不应该继续被教导;你需要学习 C11 或 C18(几乎相同)。

从 C99 开始,C 标准要求函数在使用前声明——您可以在不预先声明函数的情况下定义函数,但所有其他函数(除了 )都应该在使用或定义之前声明。您可以使用 GCC 编译器警告选项(如 (以及 和 ))来触发警告。其中,由 启用(且没有 )。请注意:正如评论中所指出的,不支持真正的 GCC(不是 Apple 的伪装)确实支持它。staticmain()-Wmissing-prototypes -Wstrict-prototypes-Wold-style-declaration-Wold-style-definition-Wold-style-declaration-Wextra-Wallclang-Wold-style-declarationclanggcc

评论

0赞 Scott Prive 8/14/2022
明智的建议,TY。我明白了,但在谷歌中,我看到这不是错别字,它存在,只是可能不在 Apple 的 gcc 中。更新了我的 VSCode tasks.json 以获取其他警告,并且 .我现在正在获取 Homebrew gcc,因为我想向自己证明是否会触发消息。unknown warning option '-Wold-style-declaration'; did you mean '-Wout-of-line-declaration'? [-Wunknown-warning-option]-std=C18-Wold-style-declaration
0赞 Scott Prive 8/14/2022
对于未来的读者来说,Homebrew 的 gcc-11 确实提供了(而 Apple 的 gcc 没有)。-Wold-style-declaration
0赞 Scott Prive 8/14/2022
因此,如果省略包含本书含义版本的 .c 文件,则使用所有警告来酿造 gcc,仍然不会引发警告/错误,大概它正在选择系统函数版本。我曾希望回到这个问题并触发某种警告(但也许通过 stdio.h 导入辅助系统的性质使这是不可能的?encrypt()
0赞 Scott Prive 8/14/2022
我运行的是:和以前一样的结果。/usr/local/Cellar/gcc/11.3.0_2/bin/gcc-11 -fdiagnostics-color=always -Wall -Wextra -Wshadow -Wmissing-prototypes -Wstrict-prototypes -Wold-style-declaration -Wold-style-definition -std=c18 -g /Users/sprive/Projects/head-first-c/message_hider.c -o /Users/sprive/Projects/head-first-c/message_hider
1赞 Jonathan Leffler 8/14/2022
请注意,在 Mac 上,是 Apple 版本的另一个名称:yields — — — —/usr/bin/gccclang/usr/bin/gcc --versionConfigured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1Apple clang version 13.0.0 (clang-1300.0.29.30)Target: x86_64-apple-darwin20.6.0Thread model: posixInstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin