c99 - 数组的外部声明

标签 c99 extern variable-declaration

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

const int array[] = {1, 3, 3, 7};

future 元素的数量可能会发生变化,所以我不想将其硬编码在括号中。

这个数组需要从多个源文件访问,所以我试图在标题中向它添加一个外部声明。但是,由于隐式数组大小,我不确定这是可能的。我尝试了两种变体:

extern const int array[]; // Warning: size of symbol `array' changed from 8 to 16
extern const int *array; // error: conflicting types for 'array'

是否可以这样做,还是我应该寻找变通办法?

最佳答案

在声明变量的头中,写:

extern const int array[];

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

extern const int array[];
extern const size_t array_size;

以及定义数组的地方:

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

您将在定义数组的位置包括标题,以确保交叉引用是正确的,一致的。如果您选择使用 int 而不是 size_t,您不会收到我的任何投诉(但如果您将编译器设置得足够挑剔,它可能对这个问题有不同的看法).

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

另见 How do I use extern to share variables between source files?

插图

答案的 MCVE ( Minimal, Complete, Verifiable Example):

ext-def.h

#include <stddef.h>

extern const int array[];
extern const size_t array_size;

ext-def.c

#include "ext-def.h"

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

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;
}

编译

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

$ 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
$

使用我的默认编译选项(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
$

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

关于c99 - 数组的外部声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47999867/

相关文章:

c - const 匿名 union 中的类型检查

c++ - C++ 中的外部:对于外部 VarX 变量::错误 LNK2001:未解析的外部符号 "unsigned int VarX"(?VarX@@3IA)

c# - 变量声明应该总是放在循环之外吗?

perl - 空哈希声明

c - 如何让夹板忽略我声明变量的位置?

c - 在代码中出现运行时错误

c - 可以将 C89 代码与 C99 代码混合使用吗?

c - 重定位被截断以适应 : R_X86_64_32

c++ - extern 可以解决这个问题还是我可以通过其他什么方式解决这个问题?

c - 为什么在表达式的括号中使用类型声明?