使用从标准库导入的全局变量时正确使用 extern?

Correct use of extern when using global variables imported from standard library?

我正在尝试学习 extern 关键字的用法。例如,我使用 getopt C 库函数。根据我对extern关键字的理解,它用于向编译器指示将要使用已在另一个文件中定义的某个变量。因此,每当我要使用 getopt 变量,如 opterroptind 等时,我是否应该(我这样做是错误的):

#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>

extern int optopt;
extern int opterr;
extern int optind;
extern char *optarg;

int main(int argc, char **argv)  {
   /* code using getopt */
}

当我查看 getopt(3) 的联机帮助页时,我看到这些声明已在 #include <unistd.h> 下提到。所以我认为这些是在那个头文件中声明的,但是当我查看头文件本身时,没有这样的声明。

所以我的问题是:在开始时使用这些语句是否有任何问题,即使是为了提高不了解 getopt 工作方式的人的可读性。此外,归根结底,如果链接器要解析引用,无论如何,是否有任何理由使用 extern?

虽然一个函数可以有多个声明或 object,但通常最好不要重新声明标准库中声明的任何内容 header。如果您声明的内容 不完全 与 header 中的内容匹配,则可能会导致问题。

此外,仅仅因为手册页上说包含 unistd.h 并不一定意味着声明在那个 specific 文件中。有问题的声明可能在 unistd.h 包含的文件中。这意味着包含 unistd.h 将为您提供所需的声明。

Also, at the end of the day if the linker is going to resolve references, anyways, is there any reason to use extern at all?

extern 关键字可以告诉 编译器 未知符号将由另一个文件提供。

考虑我们有 file1.c 的情况:

int myvariable;

file2.c与:

#include <stdio.h>

int main() {
  myvariable = 10;
  printf("myvariable is %d\n", myvariable);
  return 0;
}

尝试编译会失败:

file2.c: In function ‘main’:
file2.c:4:5: error: ‘myvariable’ undeclared (first use in this function)
    4 |     myvariable=10;

将适当的 extern 声明添加到 file2.c 允许我们编译它而不会出错:

#include <stdio.h>

extern int myvariable;

int main() {
  myvariable = 10;
  printf("myvariable is %d\n", myvariable);
  return 0;
}
  1. 头文件可以嵌套。
    unitstd.h 包含许多其他文件,您要查找的具体声明在 getopt.h

  2. 这些语句不会提高可读性,它们通过添加重复的垃圾代码来降低可读性。
    熟悉 C 但不熟悉 getopt 函数的程序员会认为这些是您的自定义变量,而不是标准库的一部分,因为标准库中的任何内容都不应重新声明。

  3. 链接器是构建可执行文件的最后一步。
    external 关键字是为了让编译器知道名称和类型,因此它可以构建带有引用的代码供链接器稍后解析。