mordicchio
mordicchio

Reputation: 145

Static 2D array in multiple files in C

I use a 2D array of chars that should be written & read by multiple functions in C.

This is my array:

static char array[3][6];

And let's say I have a function 'Function()' that modify this array. If the function is defined in the main there is no problem (the the array is correctly written & then read), but if I want to have my Function in an another file, the array is correctly written but when I return in the main is magically empty! This is my code.

main.c

#include "support.h"

int main(int argc, char *argv[])
{
  Function();
  unsigned i, j;
  for(i = 0; i < 3; i++)
  {
    for(j = 0; j < 6; j++)
        printf("[%c]", array[i][j]); 
    printf("\n"); 
  }   
  system("PAUSE");  
  return 0;
}

support.h

static char array[3][6];

support.c

void Function()
{
     char hello[6];
     hello[0] = 'H';
     hello[1] = 'E';
     hello[2] = 'L';
     hello[3] = 'L';
     hello[4] = 'O';
     hello[5] = '\0';
     strcpy(array[0], hello);            
}

No compilation error nor runtime error. One again, if I try to move everything in main.c all works, if I divide in two files it doesn't (the array is correct as soon as it returns from the Function(), then it is freed), how is it possible?

Upvotes: 1

Views: 2882

Answers (3)

AnT stands with Russia
AnT stands with Russia

Reputation: 320719

The whole point of declaring a file-level entity static is to give it internal linkage, i.e. to ensure that the entity is not visible to the other translation units and that each translation unit gets its own independent copy of such entity. That applies to both functions and objects. In your case each translation unit that includes support.h gets its own independent copy of array object. This is exactly what you achieved by declaring a static array in a header file. And that is why main.c cannot see any modifications made in support.c - these two translation units work with two completely independent arrays.

Now, when I say that the array "is not visible" from other translation units, I mean that you will not be able to refer to it by name from other translation units (i.e. you will not be able to link to it). This is not necessarily a bad thing. If you still want to declare your array as static and access it from other translation units, you can still implement this access "manually": define that array as static in one translation unit and then pass that array to all other functions as a parameter.

(Note, that in most cases passing your array around through function parameters might be a much better idea than introduction of a global variable. And that will even allow you to declare your array as local object in main.)

But if you insist on a genuine global variable, you should stop using static. Declare your arrray in the header file, per @simonc answer, and define it in one of the translation units as an object with external linkage.

Upvotes: 4

Gonmator
Gonmator

Reputation: 780

Well, you have, actually, two array defined in your program: one in the compile unit main and other in compile unit support. Compiler will compile main.c by one side and support.c by the other side, typically creating object files (usually .obj or .o). The linker put both together, resolving addresses.

Because you are defined the array as static:

static char array[3][6];

you are telling to the compiler the array is private to the compile unit. And because both main.c and support.c are including support.h, both are creating its own private array. Code in main only can see the array defined in main.c, and code in support.c only can see the array defined in support.c. When you call to Function(), that is modifying the array in support.c, not the array visible in main.c.

If you remove the static keyword from the array definition in support.h, you will have a linker error, since that symbol is defined twice (in main.c and in support.c). You must decide where do you want to define the array (in support.c or main.c) and reference to it from the other source file using the extern keyword.

Upvotes: 2

simonc
simonc

Reputation: 42195

By declaring array as static in a header file, you give each source file which includes support.h its own copy. You need to change the header to

extern char array[3][6];

and add

char array[3][6];

to a single source file.

Upvotes: 6

Related Questions