我有一个数组,其大小在源文件中定义的编译时确定。
const int array[] = {1, 3, 3, 7};
元素的数量可能会在未来发生变化,所以我宁愿不在括号中对其进行硬编码。
这个数组需要从几个源文件中访问,所以我试图在头文件中添加一个extern声明。但是由于隐式数组大小,我不确定这是否可行。我尝试了两种变体:
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命令行,而不会收到任何警告。