4

I am declaring an array of structures, and want to define the first array component in one file and second array component in another file. The following is an example.

header.h

struct st1 {
  int a;
  int b;
}

file1.c

struct st1 structure1[2];

I want to use initialize structure1 components from different files as below

file2.c

extern struct st1 structure1[0] = { 10, 100 };

file3.c

extern struct st1 structure1[1] = { 200, 500 };

Also please note that in file2.c and file3.c, the definitions are not inside functions.

If I try to compile, linker throws errors for multiple definition. After searching with Google, I got to know that the definition of extern can happen only once. Can we accomplish such kind of definition of extern array in different source code files?

Some more information: file2.c and file3.c have constants, which I will be using in file1.c. My current implementation is I am using init() functions in file2.c and file3.c. file1.c uses initialized values to decide the course of execution. Since file2.c and file3.c are exporting constants, my intention is to avoid 2 additional init calls from file1.c.

Ven
  • 83
  • 1
  • 5
  • 4
    You can't initialize an `extern` declaration. You can't define arrays of size 0. You can't initialize different bits of a single array in multiple files. – Jonathan Leffler Jun 26 '15 at 05:31
  • 2
    I'm going to point you at [How do I use `extern` to share variables between source files in C?](http://stackoverflow.com/questions/1433204/), but you may decide it is beyond what you need at the moment. It doesn't explicitly cover the mistakes you've made (or what you're trying to do) because it doesn't work — large parts of what you've attempted don't compile (missing semicolon; dimension of 0; initializing `extern`). – Jonathan Leffler Jun 26 '15 at 06:01
  • What is the actual use case? You should **edit your question** to improve it (and give the real motivation). I'm guessing that it is an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – Basile Starynkevitch Jun 26 '15 at 06:14
  • Thanks I have edited my question – Ven Jun 26 '15 at 06:55

3 Answers3

4

I've tried to make sense of what you want as much as possible, I think you would need to organise your files like below.

The header file would contain the shared symbols references that are available throughout the project as well as a few functions:

////// header.h //////
struct st1 {
    int a;
    int b;
};

extern struct st1 structure1[2];

extern void init2();
extern void init3();

Then, the implementation that contains the symbol; you could do the initialisation here as well:

////// file1.c //////
#include "header.h"

struct st1 structure1[2];

Then, the codes files in which you would do the structure changes; because this can't happen at compile time, you need to wrap this inside a function that you would call from somewhere else.

////// file2.c //////
#include "header.h"

void init2()
{
    structure1[0] = (struct st1){10, 100};
}

////// file3.c //////    
#include "header.h"

void init3()
{
    structure1[1] = (struct st1){200, 500};
}

The above two scripts have an initialise function that can be called to write into the structure. Finally, an example that demonstrates the behaviour:

////// main.c //////
#include "header.h"
#include <stdio.h>

int main(void)
{
    init2();
    init3();

    printf("s[0].a = %d, s[1].a = %d\n", structure1[0].a, structure1[1].a);

    return 0;
}

Compile like so:

cc -o file file1.c file2.c file3.c main.c
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
2

Unless your file2.c and file3.c are compiled to different executables, your question has no sense because a given executable cannot have two definitions of some same variables; you'll get a linker error on most implementations. Therefore, I guess that you have two programs sharing a common file1.c and header.h

So let's assume that file2.c and file3.c are compiled to different programs. So (on Linux) you would compile and link file1.c & file2.c into a proga program using

gcc -c -Wall -g file1.c
gcc -c -Wall -g file2.c
gcc file1.o file2.o -o proga

(or the equivalent as Makefile rules), and you would compile and link file1.c & file3.c into a different progb program

gcc -c -Wall -g file1.c
gcc -c -Wall -g file3.c
gcc file1.o file3.o -o progb

Of course, all file1.c, file2.c, file3.c have a #include "header.h" directive. Obviously the compilation of file1.c can be done once (and make would take care of that), by reusing the object file file1.o for both proga & progb

Then you probably should declare in header.h

// in header.h
extern struct st1 structure1[];

and you cannot define each component of structure1 in a different file (actually translation unit). So you can't fill structure1[0] in file2.c & structure1[1] in file3.c (unless you fill them in some explicit routines e.g. fill_first & fill_second, at runtime, which you would call explicitly, e.g. at start of main)

What you could do is (since file2.o is linked only in proga and file3.o is only in progb) having a different definition in file2.c and in file3.c (but the definition is defining the entire structure1, not some parts of it!) So you might have

 // in file2.c
 struct st1 structure1[2] = { {1,2}, {3,4} };

and

 // in file3.c
 struct st1 structure1[3] = { {0,1}, {2,3}, {3,4} };

Pragmatically, you might have an init.c file (which contains only the definition of data (like structure1) and it might use preprocessor tricks (e.g. #if or #ifdef directives) to have different initialization for proga & progb; you'll probably need to compile it differently to two different object files, e.g. init-proga.o & init-progb.o, ...

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
1

In your header.h file have

struct st1 {
    int a;
    int b;
};

extern struct st1 structure1[2];  /* Have your declaration here */

In one of your .c files, say file1.c, you can define your structure:

struct st1 structure1[2];  /* Define your structure here */

void func1()
{
  structure[0].a = 10;
  structure[0].b = 100;
}

And in file2.c:

#include "header.h"  /* Make the declaration of your structure visible here */

void func2()
{
  structure[1].a = 200;
  structure[1].b = 500;
}

Of course, the structure won't be fully initialized until both functions have been called.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Gopi
  • 19,784
  • 4
  • 24
  • 36