C-访问链接文件中的不完整类型
我在C语言中链接多个文件时遇到了一个问题。我想在编译时定义一个表示数组长度的常量,但用户每次都要在文件中实现它 要点如下: h-定义一些常量C-访问链接文件中的不完整类型,c,arrays,linker,constants,incomplete-type,C,Arrays,Linker,Constants,Incomplete Type,我在C语言中链接多个文件时遇到了一个问题。我想在编译时定义一个表示数组长度的常量,但用户每次都要在文件中实现它 要点如下: h-定义一些常量 extern const int data[]; extern const int DATA_SIZE; //other functions, not relevant int get_second_item(void); library_data.c-实现data.h中的一些函数 #include "data.h" const int DATA_SIZ
extern const int data[];
extern const int DATA_SIZE;
//other functions, not relevant
int get_second_item(void);
library_data.c-实现data.h中的一些函数
#include "data.h"
const int DATA_SIZE = sizeof(data) / sizeof(data[0]);
//can't compile because data is an incomplete type and hasn't been defined yet
int get_second_item(void)
{
return data[1];
}
public_data.c-用户使用其数据更改此设置
#include "data.h"
const int data[] = {1, 2, 3};
library_data.c和data.h首先编译为.o文件,而其他库文件#包括data.h,因此需要使用data_SIZE。移动的
const int DATA_SIZE = sizeof(data) / sizeof(data[0])
公开_data.c当然可以,但不是一个好的解决方案。您不能在未指定大小的
extern
数组上使用sizeof
(例如extern const int data[];
)
发件人:
未指定大小的外部数组是不完整类型;你不能
对其应用sizeof。sizeof在编译时运行,并且没有
它了解在另一个数组中定义的数组大小的方法
文件
您有三种选择:
file1.c:file2.c:
int数组[]={1,2,3};外部内部数组[]代码>
int-arraysz=sizeof(数组);外部内部arraysz代码>
(另见问题6.23。)
file1.h:
#定义ARRAYSZ 3
extern int数组[ARRAYSZ]代码>
file1.c:file2.c:
#包括“file1.h”#包括“file1.h”
int数组[ARRAYSZ]代码>
file1.c:file2.c:
int数组[]={1,2,3,-1};外部内部数组[]代码>
一种解决方案可能是在data.c中添加一个初始化函数,然后您必须确保在生成任何程序时调用该函数来准备数据大小
int initupdate_datasize() {
DATA_SIZE = sizeof(data) / sizeof(data[0]);
return 0;
}
您必须从data.h和library_data.c中删除常量
另一种方法是传递一个编译器定义,例如-DDATASZ=96,您将获得所有需要它的源文件。对于任何给定的平台,如果很少更改,您可以手动更新它,或者您甚至可以创建一个测试数据大小程序,该程序将从initupdate_datasize函数(或者类似的C宏)输出数据大小。根据您的构建系统,应该可以将该参数作为编译器定义传递
例如,在Makefile中,如果您使用GNU make,这可能会有所帮助:
DATA_SIZE = $(shell ./test-datasize)
CFLAGS = -O3 -Wall -DDATASZ=$(DATA_SIZE)
为什么不在同一个文件中定义
data[]
和data\u SIZE
(即public\u data.c,顾名思义,这似乎是一个合适的位置)?考虑到无论数据是什么,定义public\u数据的每个人都必须定义数据大小,这很麻烦。我知道这是一个解决方案,而且会起作用,但我想知道是否有更好的方法可以解决这个问题,用户只需定义他们的数据,库就可以处理其余的数据。“更好”的方法是首先避免全局变量,并将数据和数据量作为各种API的参数进行传递。作为一种可怕而卑鄙的做法,你可以要求用户通过你提供的一个宏定义他们的数据
,而这个宏对他们来说是隐藏的,并且还规定了幅值常数。然而,我强烈建议不要对未来的代码维护者进行如此残酷的惩罚。为什么不让数据大小成为一个函数呢?或者制作一个类来保存您需要的抽象,怎么样。@JonathanKelsey不清楚您这里所说的“类”是什么意思。谢谢-这3个解决方案就是我提出的,但不幸的是,它们都要求另一端的用户做些什么。也许extern int arraysz是最好的解决方案。