数组的外部声明

mar*_*nev 3 c99 extern variable-declaration

我有一个数组,其大小在源文件中定义的编译时确定。

const int array[] = {1, 3, 3, 7};
Run Code Online (Sandbox Code Playgroud)

元素的数量将来可能会发生变化,因此我宁愿不在括号中对其进行硬编码。

这个数组需要从几个源文件中访问,所以我试图在头文件中添加一个 extern 声明。但是,由于隐式数组大小,我不确定这是否可行。我尝试了两种变体:

extern const int array[]; // Warning: size of symbol `array' changed from 8 to 16
extern const int *array; // error: conflicting types for 'array'
Run Code Online (Sandbox Code Playgroud)

是否可以这样做,或者我应该寻找解决方法?

Jon*_*ler 6

在声明变量的标头中,写入:

extern const int array[];
Run Code Online (Sandbox Code Playgroud)

不过,您是对的,其他文件不知道数组的大小。那比较棘手。您可能会在标题中使用:

extern const int array[];
extern const size_t array_size;
Run Code Online (Sandbox Code Playgroud)

以及定义数组的位置:

const int array[] = {1, 3, 3, 7};
const size_t array_size = sizeof(array) / sizeof(array[0]);
Run Code Online (Sandbox Code Playgroud)

您将在定义数组的位置包含标头,以确保交叉引用正确无误。如果您选择使用int而不是size_t(但如果您将编译器设置得足够挑剔,它可能对这个主题有不同的看法),您将不会收到我的抱怨。

请注意,数组大小不是标准意义上的“整数常量”;例如,它不能用于case标签。如果您使用 声明另一个数组array_size,它将是一个 VLA — 可变长度数组。此类数组不能在文件范围(或static函数内的存储类)声明。

另请参阅如何extern在源文件之间共享变量?

插图

答案的 MCVE(最小、完整、可验证示例):

ext-def.h

#include <stddef.h>

extern const int array[];
extern const size_t array_size;
Run Code Online (Sandbox Code Playgroud)

ext-def.c

#include "ext-def.h"

const int array[] = {1, 3, 3, 7};
const size_t array_size = sizeof(array) / sizeof(array[0]);
Run Code Online (Sandbox Code Playgroud)

ext-use.c

#include "ext-def.h"
#include <stdio.h>

int main(void)
{
    for (size_t i = 0; i < array_size; i++)
        printf("%zu: %d\n", i, array[i]);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

汇编

在运行 macOS High Sierra 10.13.2 的 MacBook Pro 上使用 GCC 7.2.0,使用martinkunev评论中指定的选项:

$ gcc -std=c99 -pthread -O2 -fstrict-aliasing -fomit-frame-pointer -pedantic -o ext-def ext-def.c ext-use.c
$ ./ext-def
0: 1
1: 3
2: 3
3: 7
$
Run Code Online (Sandbox Code Playgroud)

使用我的默认编译选项(C11 不是 C99):

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -c ext-def.c
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -c ext-use.c
$
Run Code Online (Sandbox Code Playgroud)

在任一组选项下同样无警告。您也可以添加-pedantic到 C11 命令行而不会收到任何警告。