2

I defined a global variable char buf[1024] in one file, and what's the correct may to declare it in other files? extern char buf[1024], extern char buf[], or extern char *buf? I found extern char buf[] works and extern char *buf doesn't, but would like to know more explanations.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Wang Tuma
  • 893
  • 5
  • 14
  • 24

5 Answers5

4

You can use

extern char buf[];

but NOT

extern char *buf;

Because arrays are not pointers.

Reference: C FAQ

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • Arrays are not pointers, except sometimes. Such as: `void foo(char array[100]) { strcpy(array, "I'm really a pointer, even though my declaration looks like an array"); }` – Michael Burr Nov 22 '13 at 09:32
  • Can't single dimensional arrays be referred to by pointers with same syntax? – anishsane Nov 22 '13 at 09:47
  • 1
    @anishsane: yes, but that's because of how indexing is defined in terms of pointer arithmetic. In fact, when you index an array what happens is that the array name 'decays' to a pointer and the indexing happens via pointer arithmetic. However, arrays still aren't pointers (except for in many function parameter declarations), they just behave like pointers in many, many situations: http://stackoverflow.com/a/1462103/12711 – Michael Burr Nov 22 '13 at 15:30
0

extern char buf[] and extern char buf[1024] both are ok.

In some case, the array is implemented by pointer, such as transfering arguments between two functions.

freedoo
  • 691
  • 1
  • 5
  • 12
0

When you are making a variable as extern , you are indicating to the compiler that the symbol (address) of the variable would be found in another .o file - ( This is done during linking stage ) .

So while you are making a variable as extern , you just need to mention the name as it will give the information about address and size is not required

Srikanth
  • 447
  • 2
  • 8
0

This is the old problem of arrays and pointers being interchangeable. Arrays and pointers are not interchangeable: they just happen to be most of the time, because most of the time you use an array name in an expression, where it decays into a pointer.

This specific case of defining as char array in one file and declaring as char pointer in the other file is thoroughly explained in Expert C Programming - Deep C Secrets; see chapter 4.

The declaration of an array gives you an array, and the declaration of a pointer gives you a pointer. The difference is that an array is an address - the address of the first element - and it is not a modifiable l-value, i.e., it can't be assigned to. On the other hand, a pointer is a variable holding an address.

Usually, the context is enough to tell whether you mean the address of a variable or the contents of the variable in an assignment. The statement

i = j;

Is saying to store the contents of j in the address of i. In compilers jargon, i is said to be an l-value, and j an r-value. The compiler has to generate code that writes the contents of the memory address of j in the memory address of i.

Consider these declarations:

char a[1024];
char *a;

What happens when you write a[i] = j;?

For the former case, the compiler will just pick the address of a's contents, which, in arrays, is the address of the first element; scale i, and sum it to the base address. Then it will write the contents of the address where j is stored into that address.

For the latter case, it is quite different: the compiler has to check the memory location where a is stored, load the contents of that memory location, use THAT as an address, and write the contents of j into that address.

If you declare a characters array like this in file1.c:

char a[] = "Hello";

And then define, in file2

extern char *a;

Then, executing a[0] = 'x'; in file2.c will crash: since you told the compiler that a is a pointer, it will check the address where a's value is stored. In reality, this address is holding the character code for 'H', but the compiler mistakenly interprets that as an address, and ends up generating code to write 'x' into the address 'H', which, if you're lucky, will crash your program with a segmentation violation.

Thus, this is a case where declaration and definition must match: if you declared it as an array, define it as an array; if you declared it as a pointer, define it as a pointer. You have to declare buf as a characters array in other files. Either of these forms is legal and equivalent:

extern char buf[1024];

or

extern char buf[];
Filipe Gonçalves
  • 20,783
  • 6
  • 53
  • 70
0

Assignable global char variable. Make visible to all:

// shared_header.h
extern char current_mode[];

Define, instantiate and update:

// main.c
#include "shared_header.h"

char current_mode[160];

int main(int argc, char * argv [])
{
    strcpy(current_mode, "MODE_CONFIGURE");
    int a = randomNumber(102);

    strcpy(current_mode, "MODE_EXECUTE");
    int b = do_foo(a);
    // other stuff

    strcpy(current_mode, "MODE_TEARDOWN");
    // close up shop
}

Read or update:

// foo.c
#include "shared_header.h"

int do_foo(int a)
{
    printf("Current mode is %s", current_mode);

    if (a > 100) {
        strcpy(current_mode, "MODE_EXECUTE_SPECIAL_CASE");
        printf("Switching to mode %s", current_mode);
    }

    // do useful things
}
Elise van Looij
  • 4,162
  • 3
  • 29
  • 52