GIDForums

Go Back   GIDForums > Computer Programming Forums > C Programming Language
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read


 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 14-Dec-2007, 09:15
nickhowes nickhowes is offline
New Member
 
Join Date: Dec 2007
Location: Montana
Posts: 2
nickhowes is on a distinguished road
Question

Arrays, pointers and extern


In one source file I have:
CPP / C++ / C Code:
char buffer[256];

and I can reference the array just fine in another source file via:
CPP / C++ / C Code:
extern char buffer[];

but if I try to reference the array as a pointer:
CPP / C++ / C Code:
extern char * buffer;
I'm off in the weeds - char* buffer acts like it's uninitialized (although there are no warnings from the compiler).

Can anyone explain what's happening here? Thanks.
  #2  
Old 14-Dec-2007, 10:07
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,520
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: arrays, pointers and extern


Quote:
Originally Posted by nickhowes
...explain...?

Inside a compilation unit (that is, a single source file), the name of an array of chars is treated as a const pointer to char (the value of the pointer is the address of the first element of the array). The same for other data types.

Function calls will not distinguish between the name of an array of chars and a pointer to char. Access to variables pointed to by a pointer or to variables that are members of an array can use either pointer notation or (indexed) array notation. The two are treated exactly the same by the compiler, and the code generated by the compiler is the same. (No, I am not saying that a pointer is the same as an array; it's just notation!)

However...

When the compiler creates an object file, a symbol table is built for variables within that compilation unit. "Placeholders" are created for extern symbols (variables and functions).

The various object files are combined by the linker into a single loadable (executable) file. Details of how object files (and their symbol tables) are created are are implementation-dependent. That is, they are not specified by the C or C++ language standard.

Typically, the symbol table entry for an array will be different from the symbol table entry for a pointer. When the linker tries to reconcile and combine the symbol tables from the individual object files, they must be consistent. If you define a variable as an array in one object file, but treat it as a pointer in another, then you have a problem. The symbol types may appear to be the same, but how they get reconciled may be quite different. I hate to repeat myself, but this is implementation-dependent. What really happens may be quite different for different compilers (or even for different versions of the same compiler).

Notice that the compiler, when creating the object file, doesn't know how the variable is actually created in the other source file; it only knows what you tell it with the extern statement. So there very well may not be any compiler warnings.

Also, the linker is working with the individual object files, and has no visibility into the source files that actually created the symbol tables. There very well may not be any linker warnings.


External tools, such as the traditional UNIX "lint" and a spinoff called "splint" available for many (most?) current Linux distributions may be able look at things more completely, and may be able to spot problems like this that the compiler/linker alone does not.

Here are two files that don't play nice together:

CPP / C++ / C Code:
/* file buf.c */
char buffer[] = "Hello, world!";

CPP / C++ / C Code:
/* file testbuf.c */
#include <stdio.h>

extern char *buffer;

int main()
{
    printf("Printing buffer:\n");
    printf("buffer: <%s>\n", buffer);
    return 0;
}

I compiled them with gcc on my Linux platform (Centos 5.1, gcc version 4.1.2)
Code:
gcc -Wall -W -pedantic testbuf.c buf.c -o testbuf

There were no compiler (or linker) messages of any kind.

Here's the output:
Code:
Printing buffer: Segmentation fault

Now, if I run splint, here's what I see:
Code:
Splint 3.1.1 --- 06 Jan 2007 buf.c:2:6: Variable buffer defined with inconsistent type (arrays and pointers are not identical in variable declarations): char [] A function, variable or constant is redefined with a different type. (Use -incondefs to inhibit warning) testbuf.c:4:14: Previous declaration of buffer: char *

I changed testbuf.c as follows:
CPP / C++ / C Code:
/* file testbuf.c */
#include <stdio.h>

extern char buffer[];

int main()
{
    printf("Printing buffer:\n");
    printf("buffer: <%s>\n", buffer);
    return 0;
}

Here's the output when I ran splint:
Code:
splint testbuf.c buf.c Splint 3.1.1 --- 06 Jan 2007 Finished checking --- no warnings

Here's the output when I recompiled and executed:
Code:
Printing buffer: buffer: <Hello, world!>

Regards,

Dave

Footnote: Back in the olden days, before function prototypes were introduced into the C language, the compilers of the day didn't check for consistency between function definitions and function calls. People almost always ran their source files through lint to help spot these and certain other common errors.

Nowadays all standard C compilers test for function parameter consistency and a lot of other things that the old compilers didn't, and use of lint/splint is apparently not very common. (I typically don't run the tools for simple day-to-day utility programs that I create.)

Every now and then something like this arises (when I am trying to use Other People's Code, of course; not with my own stuff), and my pitiful little memory is jogged in such a way that I decide to run splint.
  #3  
Old 14-Dec-2007, 10:15
nickhowes nickhowes is offline
New Member
 
Join Date: Dec 2007
Location: Montana
Posts: 2
nickhowes is on a distinguished road
Smile

Re: arrays, pointers and extern


Wow, that is a perfect reply!

Thank you very much.
  #4  
Old 14-Dec-2007, 10:32
davekw7x davekw7x is offline
Outstanding Member
 
Join Date: Feb 2004
Location: Left Coast, USA
Posts: 4,520
davekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to beholddavekw7x is a splendid one to behold

Re: arrays, pointers and extern


Quote:
Originally Posted by nickhowes
...reply...
Well, it was a good question, and you stated it nicely and completely and unambiguously, and you gave it a meaningful title. A good first post!

I hope you stick around.

Regards,

Dave
 

Recent GIDBlogGoing to Iraq by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 19:03.


vBulletin, Copyright © 2000 - 2008, Jelsoft Enterprises Ltd.