数组的外部声明
extern declaration of array
我有一个数组,其大小是在 compile-time 期间在源文件中定义的。
const int array[] = {1, 3, 3, 7};
未来元素的数量可能会发生变化,所以我不想将其硬编码在括号中。
需要从多个源文件访问此数组,因此我试图在 header 中向其添加外部声明。但是,由于隐式数组大小,我不确定这是可能的。我尝试了两种变体:
extern const int array[]; // Warning: size of symbol `array' changed from 8 to 16
extern const int *array; // error: conflicting types for 'array'
是否可以这样做,或者我应该寻找 work-around?
在声明变量的header中,写:
extern const int array[];
不过你是对的,其他文件不知道数组的大小。那更棘手。您可能会在 header:
中使用
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]);
您将在定义数组的位置包括 header 以确保 cross-references 是正确的,一致。如果您选择使用 int
而不是 size_t
,您不会收到我的任何投诉(但如果您将编译器设置得足够挑剔,它可能对这个问题有不同的看法)。
注意数组大小不是标准意义上的'integer constant';例如,它不能用于 case
标签。如果您使用 array_size
声明另一个数组,它将是一个 VLA — 可变长度数组。此类数组不能在文件范围内声明(或在函数内使用 static
存储 class)。
另见 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;
}
编译
在 MacBook Pro 上使用 GCC 7.2.0 运行 macOS High Sierra 10.13.2,使用 martinkunev in a 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
$
在任何一组选项下都warning-free。您也可以在 C11 命令行中添加 -pedantic
而不会收到任何警告。
我有一个数组,其大小是在 compile-time 期间在源文件中定义的。
const int array[] = {1, 3, 3, 7};
未来元素的数量可能会发生变化,所以我不想将其硬编码在括号中。
需要从多个源文件访问此数组,因此我试图在 header 中向其添加外部声明。但是,由于隐式数组大小,我不确定这是可能的。我尝试了两种变体:
extern const int array[]; // Warning: size of symbol `array' changed from 8 to 16
extern const int *array; // error: conflicting types for 'array'
是否可以这样做,或者我应该寻找 work-around?
在声明变量的header中,写:
extern const int array[];
不过你是对的,其他文件不知道数组的大小。那更棘手。您可能会在 header:
中使用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]);
您将在定义数组的位置包括 header 以确保 cross-references 是正确的,一致。如果您选择使用 int
而不是 size_t
,您不会收到我的任何投诉(但如果您将编译器设置得足够挑剔,它可能对这个问题有不同的看法)。
注意数组大小不是标准意义上的'integer constant';例如,它不能用于 case
标签。如果您使用 array_size
声明另一个数组,它将是一个 VLA — 可变长度数组。此类数组不能在文件范围内声明(或在函数内使用 static
存储 class)。
另见 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;
}
编译
在 MacBook Pro 上使用 GCC 7.2.0 运行 macOS High Sierra 10.13.2,使用 martinkunev in a 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
$
在任何一组选项下都warning-free。您也可以在 C11 命令行中添加 -pedantic
而不会收到任何警告。