-1

I have a global variable/buffer defined in a header. I have two source files, a function library (lib.c) and a test bench (tb.c), both include the header.

In the library, I fill the global variable buffer, print the pointer value and print some of the entries of the u8 buffer by iterating the pointer, i.e. [1, 2, 3, 4, 5 etc], with pointer 0xC8004C58 (buffer length = 2144).

Now in the test bench, I grab a pointer to this same global u8 buffer in exactly the same way. Now my interpretation is that the global variable remains in the same place so the pointer to its start should be the same, however instead I get pointer 0xC80054D8. Obviously as the pointer is now different, the returned data is [0, 0, 0, 0, 0 etc].

So: If the the u8 buffer stays in the same place and is globally defined, why are my pointers to this buffer different depending on if I'm in lib.c or tb.c?

I'm creating my buffer in the header using:

static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };

I'm creating my pointer in the lib.c file using:

u32 *RxBufferPtr_Data = RxBuffer_Data;  

I'm creating my pointer in the tb.c file using:L u32 *RxBufferPtr_Data = RxBuffer_Data; or &RxBuffer_Data. Both of these return the same value, and neither are equal to the pointer that correctly prints out the data of the buffer in the lib.c file.

E. Fisher
  • 35
  • 2

4 Answers4

4

static instructs the compiler to instantiate a variable with internal linkage to the current translation unit (.c file plus all #included stuff). Internal linkage means the symbol (name) is not exported. Thus, the fact that you use matching names is irrelevant.

So, here, you get a separate instance for each .c file that #includes that header. Being separate objects, they of course have different addresses.

If you want to share a single instance (and hence address) among multiple TUs, then just do the usual:

  • Declare the variable as extern in a header - not static. Doing so indicates that it has external linkage, i.e. is defined elsewhere. Do not define the variable in the header. It must be defined only once, so...
  • Define the variable in a single .c file only.

Some light reading on the basics of static vs extern will make this all clear.

underscore_d
  • 6,309
  • 3
  • 38
  • 64
2

Each compilation unit contains its own buffer because you declared it as having internal linkage by providing keyword static in the buffer declaration in the header.

You should declare it in the header like

extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];

and in some module define it like

u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };

or just like

u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];

without the initializer because in any case it will be initialized with zeroes by the compiler as having static storage duration.

In this case the buffer will be shared by all compilation units that include the header.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

Here is the problem:

I'm creating my buffer in the header using:

static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };

The above creates a separate copy of the variable in every c file from which the header is included. In other words, your would-be-globals from separate modules are invisible to the linker, which makes them unrelated to each other, and gives them separate addresses.

If you want to make a global variable, declare it in the header like this

extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];

then define it in the file containing your main() function like this:

u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };
Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1
static u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };

You define RxBuffer_Data to staticin your head file,it tell compiler you just use this variable in this file.When lib.c include your head file,it define in lib.c.And RxBuffer_Data will re-define in tb.c when include head file,this RxBuffer_Data is a new variable.So,you can find two pointer to RxBuffer_Data is different.


If you want to define global varibal,you can define it in lib.c:

u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS] = { 0 };

and declare in your head file:

extern u32 RxBuffer_Data[MAX_DMA_RX_FIFOMODE_WORDS];

By the way,do not define global varibles in head file,because once you include this head file,you will re-define it.

BobWanghz
  • 58
  • 3
  • Sorry, but what does this add over the other 3 answers from 20 minutes ago, other than a more creative approach to spelling and punctuation? – underscore_d Jul 26 '16 at 11:19