I would like to create a static (file scope) table of data pointer, data size and data version. The problem is that the data are in external files, but constants in the extern files.
Example:
file1.c
const unsigned char data1[] =
{
0x65, 0xF0, 0xA8, 0x5F, 0x5F,
0x5F, 0x5F, 0x31, 0x32, 0x2E,
0x31, 0xF1, 0x63, 0x4D, 0x43,
0x52, 0x45, 0x41, 0x54, 0x45,
0x44, 0x20, 0x42, 0x59, 0x3A,
0x20, 0x69, 0x73, 0x70, 0x56,
// ...
};
const unsigned int data1_size =
sizeof(data1) / sizeof(data1[0]);
const unsigned int data1_version = 1;
file2.c
const unsigned char data2[] =
{
0x20, 0x44, 0x61, 0x74, 0x61,
0x20, 0x52, 0x6F, 0x77, 0x20,
0x3D, 0x20, 0x34, 0x38, 0x12,
//...
};
const unsigned int data2_size =
sizeof(data2) / sizeof(data2[0]);
const unsigned int data2_version = 1;
main.c
struct Data_Info
{
unsigned char * data_ptr;
unsigned int data_size;
unsigned int data_version;
};
extern const unsigned char data1[];
extern const unsigned int data1_size;
extern const unsigned int data1_version;
extern const unsigned char data2[];
extern const unsigned int data2_size;
extern const unsigned int data2_version;
static struct Data_Info Data_Info_Table[] =
{
// How to set this up??
// The compiler wants constant expressions here,
// and the extern is not considered a constant expression
// This is what I tried:
{ data1, data1_size, data1_version},
{ data2, data2_size, data2_version},
};
int main(void)
{
return 0;
}
I am u开发者_Go百科sing Green Hills Compiler, 4.2.3. The exact error message:
error #28, expression must have a constant value.
See my earlier post:
C: External const ints in a array of const structNote: C++ tag is included since this also applies to C++
Have you tried? (where X is 0 or 1.)
struct Data_Info
{
unsigned char const * data_ptr;
unsigned int data_size;
unsigned int data_version;
};
fileX.h
extern const struct Data_Info data_infoX;
fileX.c
const struct Data_Info data_infoX = { dataX, dataX_size, dataX_version };
main.c
const struct Data_Info const * Data_Info_Table[] =
{
&data_info1,
&data_info2
};
The problem is that the compiler doesn't know the value to place into the data_size
and data_version
members of the field. There are a couple of ways you can get around this without too much fuss.
Approach 1:
#include "data1.c"
#include "data2.c"
...
static struct Data_Info Data_Info_Table[] =
{
{ data1, sizeof(data1), 1},
{ data2, sizeof(data2), 1},
};
Approach 2:
struct Data_Info
{
unsigned char * data_ptr;
unsigned int * data_size;
unsigned int * data_version;
};
...
static struct Data_Info Data_Info_Table[] =
{
{ data1, &data1_size, &data1_version},
{ data2, &data2_size, &data2_version},
};
A third approach, as already demonstrated by jyoung, is to allocate the members in the separate data files and include their addresses in the Data_Info_Table.
When the constants are defined, use the extern keyword.
I am not that much of a C expert, but the order of initialization across different translation units is most probably undefined (I know it is undefined in C++, and it would be a huge break of compatibility if the behavior differed in C), so even if it was allowed by the compiler it would be dangerous.
Now, adding the C++ tag is most probably not going to help much, as AFAIK this is not only dependent on the language, but also in the specific version of the language: C89/C99. In C++ it works if you move the initialization to the declaration of the constant in the header file. Again, I am no C expert.
精彩评论