I read the below piece of information in a microsoft article;
https://support.microsoft.com/en-us/kb/44463
The text below presents an example of a common programming mistake, that is, confusing an array and a pointer declaration: Consider an application divided into several modules. In one module, declare an array as follows:
signed char buffer[100];
In another module, declare the following variables to access the array:
extern signed char *buffer; // FAILS extern signed char buffer[]; // WORKS
If you view the code in the CodeView debugger, it indicates that the
*buffer
declaration produces a different address than thebuffer[]
declaration does.
But I can't understand why we cannot access that array using *buffer
and we can access it using buffer[]
.
Someone please explain me what is the difference between those two types?
extern signed char buffer[];
is a chunk of memory that has an address.
extern signed char *buffer;
is a variable that may or may not point to a chunk of memory - it's a variable that contains an address that may or may not be valid.
The differences between
extern signed char *buffer;
extern signed char buffer[];
is the same as you would see when you have
signed char *buffer;
signed char buffer[100];
in a function.
I see the following differences:
Difference 1
When you have:
extern signed char *buffer;
you can use:
buffer = malloc(10);
When you have:
extern signed char buffer[];
you cannot do that.
Difference 2
In the first case, it is possible for buffer
to be NULL. In the second case, it is not.
Difference 3
&buffer
result in different types. For example, you can use:
printf("pointer 1: %p\n", &buffer+1);
in the first case but you cannot use that in the second case. For &buffer+1
to work in the second case, you'll have to know the size of the array.
This question is more about C linker than about C language.
Although there is a context where signed char *buffer
and signed char buffer[]
mean the same thing, extern
is not one of them. Using extern
asks the compiler to defer resolving of the external definition to linker. Linker has to be very particular about the difference between pointers and arrays, because the two have different structure in memory, and cannot be treated interchangeably.
Note that although these declarations are different to the linker, they do not change what a programmer could do with such an external array: in both cases you have no access to the size of the declared array (ie 100), the syntax to access array elements stays the same, and the pointer arithmetic remains the same.
In one module, you define an array of signed char
of size 100
named buffer
. This object will use 100 bytes of memory:
signed char buffer[100];
In another module, you declare buffer
to be something else, a pointer to signed char
, that is 4 or 8 bytes of memory that may hold the address of an array or that of a single char
.
extern signed char *buffer;
The compiler only knows one module at a time, so it cannot check whether this declaration is consistent with the actual definition . It compiles code consistently with this declaration, emitting machine code that refers to an external symbol buffer
that will be resolved at link time.
At link time, the linker does not know about types, it only relies on names. Therefore it resolves the references to buffer
from one module with the actual address of the definition from the other module.
At runtime, you get undefined behaviour, because one module uses buffer
as an array of signed char
, which it is, and the other loads the value of a pointer from the same address, interpreting the bytes completely differently.
Declarations belong in header files and should always be included in the source file that actually defines the object declared in the header.
See these questions in the C FAQ List:
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.